$pull is not working for array in mongoose (MongoDB) - node.js

In mongoDB (Through mongoose), I am trying to remove an element in array of a collection and using $pull operator for that, but it is not working.
Rooms collection in mongoDB
{
"_id":"sampleObjectId",
"users": ["email1#example.com", "email2#example.com"]
}
Backend code to remove a user (mongoose using Node.js)
Rooms.update(
{ _id: "sampleRoomId" },
{
$pull: {
users: "email1#exmple.com" }
},
}
)
Noting happens to collection on running this code, no change happens. code runs with no errors and in output it says "nModified":0 .
I have no idea how to remove a user from collection.

//actual code output from the mongo shell. This is working as expected. check if you given //correct value in object_id query parameter.
> db.rooms.find();
{ "_id" : "sampleObjectId", "users" : [ "email1#example.com", "email2#example.com" ] }
> db.rooms.update(
... {_id: "sampleObjectId"},
... {$pull:{users:"email1#example.com"}}
... );
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.rooms.find();
{ "_id" : "sampleObjectId", "users" : [ "email2#example.com" ] }
> db.version();
4.2.6
>

Related

How to update with the multiples records in mongodb using node js

here i want to update with the multiple records so i'm using bulk operations and im trying to set the isenrolledcourse to true but its not updating
what i'm passing wrong here, thanks in advance
idsList = [ 60f6897c3b996238808ca5e2, 60f6f729012963152c7d0a0b ]
const Course = db.courses;
Course.bulkWrite([
{ updateMany :
{
"filter" : { _id : {$in : idsList }},
"update" : { $set: { "isenrolledcourse": true}},
"upsert" : true,
}
}
])
updateMany would do, you do not need bulkWrite, because you are doing single kind of action i.e. update. bulkWrite is used to carry on different kinds of actions together.
Course.updateMany(
{_id : {$in : idsList }},
{$set: { "isenrolledcourse": true}},
{upsert:true}
)

How to compare array mongodb query

I am currently building a cart system on my mongodb ecommerce app. I need help on how to query and compare array.
here document of cart:
{
"_id" : ObjectId("5d0531e27c8fa1029017ea20"),
"user" : ObjectId("5d0371319315c715fc34b0b0"),
"active" : true,
"item" : [
{
"product" : ObjectId("5d013eb63a2bdd11a46c8dd3"),
"option" : [
{
"name" : "Ukuran",
"value" : "Biru"
}
],
"quantity" : 1
},
{
"product" : ObjectId("5d013eb63a2bdd11a46c8dd3"),
"option" : [
{
"name" : "Ukuran",
"value" : "Biru"
}
],
"quantity" : 1
}
],
"created_at" : ISODate("2019-06-15T17:58:58.762Z"),
"updated_at" : ISODate("2019-06-15T17:59:13.334Z"),
"__v" : 0
}
I want to compare object of item.option field, so my cart system is if cart on database have same object option i will add quantity, otherwise push new object to item.
so current I am not asking on how to implement my cart system, but I want to compare each item.option object
I've already tried this
const cart = await CartModel.find({
"item.option": option
})
and get error Error: Query filter must be an object, got an array
Solved by myself, after many experiment finally i combine $in and $elemMatch for compare each array of object
// this is will dynamic
const optionArray = [
{
"name": "Warna",
"value": "Biru"
},
{
"name": "Ukuran",
"value": "XL"
}
]
const compareOptionQuery = []
for (let i = 0; i < optionArray.length; i++) {
compareOptionQuery.push({
$elemMatch: {
...option[i]
}
})
}
const cart = await CartModel.aggregate([
{
$and: [
{
_id: cartId,
user: userId
},
{
'item.option': {
$in: [...compareOptionQuery]
}
}
]
}
])
The issue with your implementation is that in CartModel.find("item.option": option) your filter (first parameter) encounters an array instead of an object.
This is because you are trying to call for an object option from item, however option is as element of an array field item.
If you wish to access item from an array field, you must specify conditions on the elements in the array field item using {<array field>: {<operator1>: <value1>}} like so:
CartModel.find({
item: {$option: option}
})

findByIdAndDelete a subdocument with mongodb and mongoose, ( nodejs )

I am trying to delete a subdocument that i have in my very deep nested schema...
i am using findByIdAndUpdate method but it is not removing the subdocument.
i have this in my nodejs
//I pretend to delete a subdocument inside the array "items"
storeCtrl.deleteAlmacen = (req, res) => {
storeModel.findByIdAndDelete(req.params.id).then(() => {
res.json('deleted')
}).catch((err) => {
res.json(err)
})
}
And it is my schema
// i did not copy and paste, so maybe has some syntax errors
{
"_id" : ObjectId("5c6cd20f13f0940e0cc214c5"),
"store" : [
{
"_id" : ObjectId("5c6cd20f13f0940e0cc214c6"),
"office" : [
{
"_id" : ObjectId("5c6cd21f13f0940e0cc214c8"),
"items" : [
{
"_id" : ObjectId("5c6cd22e13f0940e0cc214cb"),
"pen" : "3",
"paperId" : "a4"
}
],
"employees" : [ ],
"work" : 1
}
]
}
]
}
Do i have to use other method instead findByIdAndDelete?
Take a look at this solution: Update nested subdocument in Mongoose
Long story short, you should be using separate models, all of which reference each other. It's going to be a pain to change what you have now, but in all reality it's going to be MUCH cleaner.
You should have a Store model that references Office and an Office model that references an Items model

MongoDB/Mongoose $inc subdocument does not modify anything

I am trying to update a subdocument inside of an array.
{
"_id" : ObjectId("5a7a017e0aa5311d9c75c86b"),
"campaignId" : "5a7a017e0aa5311d9c75c86b",
"subCampaigns" : [
{
"_id" : ObjectId("5a7a0eee6849f507d0499a18"),
"name" : "test5",
"campaignId" : ObjectId("5a7a017e0aa5311d9c75c86b"),
"subCampaignId" : "1aKysewspn6CqNGVkv6pyL"
}
{
"name" : "test8",
"amountRaised" : 20.0,
"campaignId" : ObjectId("5a7a017e0aa5311d9c75c86b"),
"subCampaignId" : "5a7a153fe035de396c6f5b3c",
"_id" : ObjectId("5a7a153fe035de396c6f5b3c")
}
],
"name" : "test8",
"__v" : 12,
"totalDonated" : 110.0
}
When I run:
db.getCollection('campaigns').update({"_id": ObjectId("5a7a017e0aa5311d9c75c86b"), "subCampaigns.subCampaignId":"5a7a153fe035de396c6f5b3c"}, {$inc: {"subCampaigns.$.amountRaised": 10}})
In the mongo console it updates the sub document fine. But when I run this in my Mongoose code:
this.campaignModel.update(
{ campaignId: '5a7a017e0aa5311d9c75c86b', 'subCampaigns.subCampaignId': '5a7a153fe035de396c6f5b3c' },
{ $inc: { 'subCampaigns.$.amountRaised': 10}},
(err: any, subResult: any) => {...
The sub document does not have its amountRaised field incremented. From what I can tell they should be identical calls?
If I run an inc at the level higher:
this.campaignModel.findOneAndUpdate(
{campaignId: object.campaignId},
{$inc: {totalDonated: donationAmount}},
() => {...
It works fine, so this must have something to do with the sub document?
I have been playing around with multiple mongoose calls for most of the day but cannot seem to get it to update correctly.

$addToSet in a nested Array item

Considering the following
User collection & sample User document
{
"_id" : ObjectId("575c01f7b8e5999addeb598c"),
"username" : "test.1#gmail.com",
"password" : "<password>",
"firstName" : "Test,
"lastName" : "User"
}
I am trying to run an update request to add an entry in userData.eventData which is meant to be an array
In mongo script I can do
> db.Users.update({_id: ObjectId("575c01f7b8e5999addeb598c")}, {"$addToSet":{"userData.eventData":"My event"}} )
And I have the following result : userData is created as an Object and eventData as a nested Array
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.Users.find({_id: ObjectId("575c01f7b8e5999addeb598c")})
{ "_id" : ObjectId("575c01f7b8e5999addeb598c"), "username" : "test.1#gmail.com", "password" : "<password>", "firstName" : "Test", "lastName" : "User", "userData" : { "eventData" : [ "My event" ] } }
While running the same logic in mongo (using driver version 2.1.21)
// with a properly initialized db object
db.collection("Users").update({"_id" : ObjectId("575c01f7b8e5999addeb598c")}, {"$addToSet": { "userData.eventData": "My Event"}}, function(err, result) {
// do something
});
I receive the following response
result:Object
n:0
nModified:0
ok:1
And indeed the database entry is unchanged.
Is that the way it is meant to behave? I can easily fix this by creating the userData.eventData array but I found disturbing the fact that node's Mongo driver and mongo shell didn't behave the same on this
Thanks in advance for your help & advice
Edit 13/6/16
Mistake was on my side, I missed a 'new' before 'ObjectId(...' in node. With it, it behaves exactly the same as in mongo shell (i.e. 'userData' is created as an Object and it includes 'eventData' array)
No issue, then :)
Update, updates an already existing object in your document.
What you want is insert or use upset which creates a new document when no document matches the query criteria
db.collection.update(
{ name: "Andy" },
{
name: "Andy",
rating: 1,
score: 1
},
{ upsert: true }
);
If you wanted to add an object to your array, you would need $push
// Insert a document in the capped collection
function push (db, collection, search, data, callback) {
db.collection(collection).update(
search, {
$push: data
}, function (err, result) {
console.log("New object pushed");
callback(err);
});
}

Resources