Mongoose deleteMany using _id on nodejs - node.js

i have a ids of array ['123','456', '789']. i want delete all this array in mongodb
How i user it:
ScheduleModel.deleteOne({ _id: ['123','456', '789'] });
this is not working because this is not object Id
what i Need :
ScheduleModel.deleteOne({ _id: [ObjectId('123'), ObjectId('456'), ObjectId('789')] });
How to add object Id in array data. any how to resolve this issues. i need a solution on this.

It's not about ObjectId. you are using wrong syntax. You must use $in statement
ScheduleModel.deleteMany({ id: { $in: ['123','456','789'] } });

Use deleteMany with proper syntax.When there are many objectId at time Use $in.
Try this :
var deleteCondition = {
_id : {
//In Array you can pass your objectId
$in : ['123','456','789']
}
//You can pass other conditions
}
//deleteMany
ScheduleModel.deleteMany(deleteCondition, function (err, res) {
if (res) console.log(res)
})

Related

Remove object by id from an array in mongoose

So this seems pretty straightforward but I cant seem to get it to work.I have a document in mongodb and i m using mongoose All i need to do is find user by id, get the document and delete one specified object from an array of objects. Here is the Structure:
report:[
{
asset_report_id:234,
name:'somethign,
},
{
asset_report_id:23,
name:'somethign,
},
{
asset_report_id:111,
name:'somethign,
}
]
I tried this :
User.findOne({_id: request.decodedTokenData.userId})
.exec()
.then(user=>{
const result = user.reports.find( ({ asset_report_id }) => asset_report_id === assetID );
console.log('IN FIND',result);
})
.catch(err=>console.log(err))
Now i do get the result which is great and i can delete but isn't there a method to do it with mongoose directly? More alongthe lines of plain mongo version of :
db.removeObject.update( {'_id':ObjectId("5c6ea036a0c51185aefbd14f")},
{$pull:{"reports":{"asset_report_id":234}}},false,true);
So the correct solution is:
await User.updateOne( {'_id':ObjectId("5c6ea036a0c51185aefbd14f")},
{$pull:{"report":{"asset_report_id":234}}},false,true)
since the data model contains "report" array

findAndModify or findOneAndUpdate - "is not a function"

First of all, which one is best?
findAndModify or findOneAndUpdate or findByIdAndUpdate?
In my case I got a table like this:
seqkeys
{
"_id" : "invoice",
"seq" : NumberInt(1)
},
{
"_id" : "receipt",
"seq" : NumberInt(1)
}
And I want to find the seq number for invoice, add 1 and save. (and then use that number to save the real invoice record in the invoice table)
But I cant get this to work, I constantly get
TypeError: seqkeysTable.findAndModify is not a function
So here is my model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var seqkeysSchema = new Schema({
_id: String, // Table Name
seq: Number // Sequence Number
});
module.exports = mongoose.model('seqkeysModel', seqkeysSchema,'seqkeys');
And here is my findkey nodejs function....
var seqkeysModel = require('../../models/seqkeysModel');
var seqkeysTable = mongoose.model('seqkeysModel');
var findKey = function(tableName) {
return new Promise((resolve, reject) => {
seqkeysTable.findAndModify(
{ "_id": tableName },
{ $inc: {"seq":1} },
{ new: true }
,function (err, data) {
if (err) {
reject(new Error('findKey ERROR : ' + err));
return;
} else {
resolve(data.seq);
};
});
})};
Mongoose has findOneAndUpdate (equivalent of mongoBD findAndModify. MongoDB also introduced findOneAndUpdate in version >= 3.2) and findByIdAndUpdate. That's why findAndModify won't work with Mongoose.
As to which one is better, in findOneAndUpdate you can pass query object containing multiple fields while findByIdAndUpdate only takes id as the first parameter.
findAndModify is a function of MongoDB, That's why that doesn't work with Mongoose.
Both findOneAndUpdate and findByIdAndUpdate works well with Mongoose, perhaps if you wish to use _id to search in the database then go for findByIdAndUpdate else if you are using a different field to search in the database then use findOneAndUpdate.
However, if you try to use findAndModify in MongoDB, you might get the following warning :
DeprecationWarning: collection.findAndModify is deprecated. Use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead.
To eliminate this use the following in your code :
mongoose.set('useFindAndModify', false);
Just in case, difference between findByIdAndUpdate & findOneAndUpdate :
findByIdAndUpdate(id, ...) is equivalent to findOneAndUpdate({ _id: id
}, ...)

Mongo / Express Query Nested _id from query string

Using: node/express/mongodb/mongoose
With the setup listed above, I have created my schema and model and can query as needed. What I'm wondering how to do though is, pass the express request.query object to Model.find() in mongoose to match and query the _id of a nested document. In this instance, the query may look something like:
http://domain.com/api/object._id=57902aeec07ffa2290f179fe
Where object is a nested object that exists elsewhere in the database. I can easily query other fields. _id is the only one giving an issue. It returns an empty array of matches.
Can this be done?
This is an example and not the ACTUAL schema but this gets the point across..
let Category = mongoose.Schema({
name: String
})
let Product = mongoose.Schema({
name: String,
description:String,
category:Category
})
// sample category..
{
_id:ObjectId("1234567890"),
name: 'Sample Category'
}
// sample product
{
_id:ObjectId("0987654321"),
name:'Sample Product',
description:'Sample Product Description',
category: {
_id:ObjectId("1234567890"),
name: 'Sample Category'
}
}
So, what I'm looking for is... if I have the following in express..
app.get('/products',function(req,res,next){
let query = req.query
ProductModel.find(query).exec(function(err,docs){
res.json(docs)
})
})
This would allow me to specify anything I want in the query parameters as a query. So I could..
http://domain.com/api/products?name=String
http://domain.com/api/products?description=String
http://domain.com/api/products?category.name=String
I can query by category.name like this, but I can't do:
http://domain.com/api/products?category._id=1234567890
This returns an empty array
Change your query to http://domain.com/api/object/57902aeec07ffa2290f179fe and try
app.get('/api/object/:_id', function(req, res) {
// req._id is Mongo Document Id
// change MyModel to your model name
MyModel.findOne( {'_id' : req._id }, function(err, doc){
// do smth with this document
console.log(doc);
});
});
or try this one
http://domain.com/api/object?id=57902aeec07ffa2290f179fe
app.get('/api/object', function(req, res) {
var id = req.param('id');
MyModel.findOne( {'_id' : id }, function(err, doc){
console.log(doc);
});
})
First of all increase your skills in getting URL and POST Parameters by this article.
Read official Express 4.x API Documentation
Never mind I feel ridiculous. It works just as I posted above.. after I fixed an error in my schema.

Find and delete a field in mongodb using mongoose [duplicate]

I'm using the Mongoose Library for accessing MongoDB with node.js
Is there a way to remove a key from a document? i.e. not just set the value to null, but remove it?
User.findOne({}, function(err, user){
//correctly sets the key to null... but it's still present in the document
user.key_to_delete = null;
// doesn't seem to have any effect
delete user.key_to_delete;
user.save();
});
In early versions, you would have needed to drop down the node-mongodb-native driver. Each model has a collection object that contains all the methods that node-mongodb-native offers. So you can do the action in question by this:
User.collection.update({_id: user._id}, {$unset: {field: 1 }});
Since version 2.0 you can do:
User.update({_id: user._id}, {$unset: {field: 1 }}, callback);
And since version 2.4, if you have an instance of a model already you can do:
doc.field = undefined;
doc.save(callback);
You'll want to do this:
User.findOne({}, function(err, user){
user.key_to_delete = undefined;
user.save();
});
I use mongoose and using any of the above functions did me the requirement. The function compiles error free but the field would still remain.
user.set('key_to_delete', undefined, {strict: false} );
did the trick for me.
At mongo syntax to delete some key you need do following:
{ $unset : { field : 1} }
Seems at Mongoose the same.
Edit
Check this example.
Try:
User.findOne({}, function(err, user){
// user.key_to_delete = null; X
`user.key_to_delete = undefined;`
delete user.key_to_delete;
user.save();
});
if you want to remove a key from collection try this method.
db.getCollection('myDatabaseTestCollectionName').update({"FieldToDelete": {$exists: true}}, {$unset:{"FieldToDelete":1}}, false, true);
Could this be a side problem like using
function (user)
instead of
function(err, user)
for the find's callback ? Just trying to help with this as I already had the case.
Mongoose document is NOT a plain javascript object and that's why you can't use delete operator.(Or unset from 'lodash' library).
Your options are to set doc.path = null || undefined or to use Document.toObject() method to turn mongoose doc to plain object and from there use it as usual.
Read more in mongoose api-ref:
http://mongoosejs.com/docs/api.html#document_Document-toObject
Example would look something like this:
User.findById(id, function(err, user) {
if (err) return next(err);
let userObject = user.toObject();
// userObject is plain object
});
the problem with all of these answers is that they work for one field. for example let's say i want delete all fields from my Document if they were an empty string "".
First you should check if field is empty string put it to $unset :
function unsetEmptyFields(updateData) {
const $unset = {};
Object.keys(updatedData).forEach((key) => {
if (!updatedData[key]) {
$unset[key] = 1;
delete updatedData[key];
}
});
updatedData.$unset = $unset;
if (isEmpty(updatedData.$unset)) { delete updatedData.$unset; }
return updatedData;
}
function updateUserModel(data){
const updatedData = UnsetEmptyFiled(data);
const Id = "";
User.findOneAndUpdate(
{ _id: Id },
updatedData, { new: true },
);
}
I believe that, if you desire remove a specific field into a collection, you should do this:
User.remove ({ key_to_delete: req.params.user.key_to_delete});
you can use
delete user._doc.key

Trying to remove a subdocument in Mongoose gives me an internal mongoose error

I have a schema as follows (simplified):
var Permission = new Schema({
_id: String, // email address
role: String // "admin" or "member"
});
var Org = new Schema({
name: {type: String, index: {unique: true, dropDups: true}, trim: true},
permissions: [Permission]
});
An example document would look like this:
{
"name": "My Org",
"permissions" : [
{"_id" : "joe#gmail.com", "role" : "admin"},
{"_id" : "mary#gmail.com", "role" : "member"}
]
}
I am trying to delete one of the permissions rows, using the command org.permissions.remove(req.params.email), as shown in context below:
exports.removePermissions = function(req, res) {
var name = req.params.name;
return Org
.findOne({name: name})
.select()
.exec(function(err, org) {
if (err) return Org.handleError(res, err);
if (!org) return Org.handleError(res, new Error("#notfound " + name));
org.permissions.remove(req.params.email);
org.save(function(err, org) {
if (err) return Org.handleError(res, err);
else return res.send(org);
});
});
};
When I do this, I get the following error:
TypeError: Cannot use 'in' operator to search for '_id' in joe#gmail.com
at EmbeddedDocument.Document._buildDoc (/../node_modules/mongoose/lib/document.js:162:27)
at EmbeddedDocument.Document (/../node_modules/mongoose/lib/document.js:67:20)
at EmbeddedDocument (/../node_modules/mongoose/lib/types/embedded.js:27:12)
at new EmbeddedDocument (/../node_modules/mongoose/lib/schema/documentarray.js:26:17)
at MongooseDocumentArray._cast (/../node_modules/mongoose/lib/types/documentarray.js:62:10)
at Object.map (native)
at MongooseDocumentArray.MongooseArray.remove (/../node_modules/mongoose/lib/types/array.js:360:21)
at model.Org.methods.removePermissions (/../models/org.js:159:20)
The only thing I can think of is that Mongoose does not support _id fields that are not ObjectID's? This is strange, because I use these elsewhere in my code and it works fine (e.g. org.permissions.id("joe#gmail.com") works).
Any suggestions much appreciated!
I'm not sure why using remove there isn't working, but you can do this atomically with findOneAndUpdate and the $pull operator:
exports.removePermissions = function(req, res) {
var name = req.params.name;
return Org.findOneAndUpdate(
{name: name},
{$pull: {permissions: {_id: req.params.email}}},
function(err, org) {
// org contains the updated doc
...
});
};
As per this answer, you need to call remove() on the subdocument you want to remove, rather than on the entire subdocument array.
So, change:
org.permissions.remove(req.params.email);
to:
org.permissions.id(req.params.email).remove();
This two-step method has the added advantage over the answer supplied by #JohnnyHK in that you can validate whether the subdocument actually exists before removing it. This can be useful if you'd like to send a 404 response indicating that the subdocument doesn't exist - as far as I am aware, this isn't possible using the $pull atomic operator.
Note that this also will only work if your subdocument array has a schema, as illustrated in the question. If it doesn't, or it has a schema type of Mixed, the collection returned from the database will be a plain array rather than a Mongoose-enhanced array. This means that there is no .id() function. In this case, I would use lodash#remove instead:
_.remove(org.permissions, (function(permission) {
return permission._id.toString() === req.params.email;
}));

Resources