The userlist collection contains documents of the following format.
{
"_id" : ObjectId("5381d32ce72cc794166eede2"),
"name" : "Haseeb",
"password" : "dgkhan",
"email" : "hasseeb#yahoo.com",
"address" : "237 D, Faisal Town , Lahore",
"phone" : "5162806"
}
I intend to add another member in the existing document such that the resultant document looks like this.
{
"_id" : ObjectId("5381d32ce72cc794166eede2"),
"name" : "Haseeb",
"password" : "dgkhan",
"email" : "hasseeb#yahoo.com",
"address" : "237 D, Faisal Town , Lahore",
"phone" : "5162806",
"purchases" : [{
"itemID": xyz,
"quantity": 142
},
{
"itemID": kjh,
"quantity": 987
}
}]
}
For this I have written the following mongoskin query, but it is not performing any updates.
db.collection('userlist').update(
{_id:req.session._id},
{
'$push': { purchases: {
itemID: item.ID,
quantity: item.quantity
}
}
}, function(err) {
if (err) throw err;
console.log('Updated!');
});
}
Value of req.session._id = 5381d32ce72cc794166eede2 i.e a valid _id field of a docuemnt in my collection whereas item.ID and item.quantity are also valid strings.
Any help would be really appreciated.
I'm more familiar with Mongoose, but looking at the docs you could probably either use:
collection.updateById(req.session._id, ...)
or
collection.update({_id: toObjectID(req.session_id)}, ...)
I think you should be using $set instead of $push.
A good resource for this specific question is: http://docs.mongodb.org/manual/reference/method/db.collection.update/#db.collection.update
Something like this. You need to include the $each syntax.
db.collection('userlist').update(
{_id:req.session._id},
{
$push { purchases: { $each: {
itemID: item.ID,
quantity: item.quantity
}
}
}
}, function(err) {
if (err) throw err;
console.log('Updated!');
});
}
Related
I have few records in mongo db and i need to update all those records with different values at a single stretch which matches its "id".
The record in mongo db will not have value for "status" & "timestamp" and i need to update these.
When i try to update the record, the update values are getting newly inserted into another new collection and not updating in my existing collection.
var parsedRes = [{
"id": "1000000",
"mobilenum": "2323442343",
"code": "SC0",
"status": "1",
"timestamp": "1602771846"
}, {
"id": "1000001",
"mobilenum": "3323442343",
"code": "SC0",
"status": "8",
"timestamp": "1602771843"
}, {
"id": "1000002",
"mobilenum": "4323442343",
"code": "SC0",
"status": "3",
"timestamp": "1602771842"
}, {
"id": "1000003",
"mobilenum": "5323442343",
"code": "SC0",
"status": "1",
"timestamp": "1602771844"
}
]
var updateData = [];
for (var i = 0; i < parsedRes.length; i++) {
updateData.push({
updateOne: {
filter: { ID: parsedRes[i].id },
update: {
$set: {
mobile: parsedRes[i].mobilenum,
code: parsedRes[i].code,
status: parsedRes[i].status,
timestamp: parsedRes[i].timestamp
}
}, upsert: true
}
});
}
return new Promise(function (resolve, reject) {
mongomodel.bulkWrite(updateData, { ordered: false }, async function(err, result) {
if (err) {
console.log("errorrrrrrrr : ",err)
reject(err)
} else {
console.log("result : ****************** ",result)
resolve(result)
}
})
updateData = [];
})
Could anyone please help me on where i go wrong. Is there any other approach to do this, please share. Thanks in advance.
sample document from db:
#wak786 Please find the sample document
db.mongomodel.find()
{ "_id" : ObjectId("5f896c9d1148a810d90a8261"), "id" : "1000000", "status" : "1", "mobilenum" : "2323442343", "code" : "TA0","UpdateDate" : "1602771841", "createdAt" : ISODate("2020-10-16T09:49:17.693Z"), "updatedAt" : ISODate("2020-10-16T09:49:17.693Z") }
{ "_id" : ObjectId("5f896c9d1148a810d90a8262"), "id" : "1000001", "status" : "8", "mobilenum" : "3323442343", "code" : "OR0","UpdateDate" : "1602771841", "createdAt" : ISODate("2020-10-16T09:49:17.693Z"), "updatedAt" : ISODate("2020-10-16T09:49:17.693Z") }
{ "_id" : ObjectId("5f896c9d1148a810d90a8263"), "id" : "1000002", "status" : "1", "mobilenum" : "4323442343", "code" : "OC0","UpdateDate" : "1602771841", "createdAt" : ISODate("2020-10-16T09:49:17.693Z"), "updatedAt" : ISODate("2020-10-16T09:49:17.693Z") }
{ "_id" : ObjectId("5f896c9d1148a810d90a8264"), "id" : "1000003", "status" : "1", "mobilenum" : "5323442343", "code" : "TC0","UpdateDate" : "1602771841", "createdAt" : ISODate("2020-10-16T09:49:17.693Z"), "updatedAt" : ISODate("2020-10-16T09:49:17.693Z") }
Some of the things I notice here are :
You are using upsert:true. It will add new documents to collection if your filter query doesn't find any matching documents. SO setting upsert:false will solve the problem of new documents getting added to collection.
Another problem I suspect is in following line of code.
filter: { ID: parsedRes[i].id },
I think it should be id instead of ID (I am assuming it is not a Javascript constant).
If you have const ID = "id" somewhere in your code then ignore this point.
EDIT :-
Can you try by removing $set becoz what I see in latest mongoose docs, $set is not needed anymore.
This is from mongoose docs.
https://mongoosejs.com/docs/api.html#model_Model.bulkWrite
{
updateOne: {
filter: { name: 'Eddard Stark' },
// If you were using the MongoDB driver directly, you'd need to do
// `update: { $set: { title: ... } }` but mongoose adds $set for
// you.
update: { title: 'Hand of the King' }
}
},
I have the below User document. I want to return a list of all 'friends' where friends.name is equal to "Bob".
{
"_id" : ObjectId("5a4be9f200471a49d2e23ce4"),
"name": "James"
"friends" : [
{
"_id" : ObjectId("5a4be9f200471a49d2e23ce6"),
"dob" : ISODate("2018-01-02T00:00:00.000Z"),
"name" : "Bob"
},
{
"_id" : ObjectId("5a4be9f200471a49d2e23ce5"),
"dob" : ISODate("2018-01-02T00:00:00.000Z"),
"name" : "Fred"
}
],
"__v" : 0
}
When I try to query using the below, its working but its returning the whole friends list, not just Bob.
User.findOne({ "friends.name": "Bob" }, function(err, friends) {
if(err) return next(err);
res.send(friends);
});
How can I query so I only to return Bob object and not Fred?
Your query is correct, but it returns all user documents having at least one friend matching your condition.
If you just want matching items from the friends collection, you might do something like this.
db.User.aggregate([
{ $unwind: "$friends" },
{ $replaceRoot: { newRoot: "$friends" } },
{ $match: { name: "Bob" }}
])
My document structure is as follows:
{
"_id" : ObjectId("54d81827e4a4449d023b4e34"),
"cat_id" : 1,
"description" : "Refridgerator",
"image" : "refridgerator",
"parent" : null,
"slug" : "refridgerator"
}
{
"_id" : ObjectId("54dc38bce4a4449d023b4e58"),
"name" : "Ice Cream",
"description" : "Ice Cream",
"image" : "ice-cream.jpg",
"slug" : "ice-cream",
"parent" : "54d81827e4a4449d023b4e34"
}
{
"_id" : ObjectId("54dc3705e4a4449d023b4e56"),
"name" : "Chocolate",
"description" : "Chocolate",
"image" : "chocolate.jpg",
"slug" : "chocolate",
"parent" : "54d81827e4a4449d023b4e34"
}
I’m making a category hierarchy using mongodb and nodejs.
Now I wish to query for _id = ‘54d81827e4a4449d023b4e34’ (Refridgerator) and should get back all the child categories
How to achieve the above in nodejs?
Also, nodejs uses async call to the database, I’m unable to get the json structured with parent – child relations.
How would I do the async call for this?
You want the refridgerator and all the subcategories?
And async is also a problem?
I think you can use aggregation here.
Say you're looking for a category with _id variable which is an ObjectId of what you want, and it's subcategories.
db.yourCollection.aggregate({
// get stuff where you have the parent or subcats.
$match: {
$or: [
{_id: ObjectId("54de8b9f022ff38bbf5e0530")},
{parent: ObjectId("54de8b9f022ff38bbf5e0530")}
]
}
},
// reshape the data you'll need further on from each mached doc
{
$project: {
_id: false,
data: {
id: '$_id',
name: '$name'
// I guess you'll also want the `slug` and `image` here.
// but that's homework :)
},
parent: '$parent'
}
},
// now put a common _id so you can group them, and also put stuff into arrays
{
$project: {
id: {$literal: 'id'},
mainCategory: {
// if our parent is null, put our data.
// otherwise put null here.
$cond: [{$eq: [null, '$parent']}, {_id: '$data.id', name: '$data.name'}, undefined]
},
subcat: {
// here is the other way around.
$cond: [{$ne: [null, '$parent']}, {_id: '$data.id', name: '$data.name'}, null]
}
}
// that stage produces for each doc either a mainCat or subcat
// (and the other prop equals to null)
},
// finally, group the things so you can have them together
{
$group: {
_id: '$id',
// a bit hacky, but mongo will yield to it
mainCategory: {$max: '$mainCategory'},
subCategories: {
// this will, unfortunately, also add the `null` we have
// assigned to main category up there
$addToSet: '$subcat'
}
}
},
// so we get rid of the unwanted _id = 'id' and the null from subcats.
{
$project: {
_id: false,
mainCategory: 1,
subCategories: {
$setDifference: ['$subCategories', [null]]
}
}
})
Given this data set:
[{
"_id" : ObjectId("54de8b9f022ff38bbf5e0530"),
"name" : "Fridge",
"parent" : null
},
{
"_id" : ObjectId("54de8bba022ff38bbf5e0531"),
"name" : "choco",
"parent" : ObjectId("54de8b9f022ff38bbf5e0530")
},
{
"_id" : ObjectId("54de8bc8022ff38bbf5e0532"),
"name" : "apple",
"parent" : ObjectId("54de8b9f022ff38bbf5e0530")
}
I get this result:
{
"result" : [
{
"mainCategory" : {
"_id" : ObjectId("54de8b9f022ff38bbf5e0530"),
"name" : "Fridge"
},
"subCategories" : [
{
"_id" : ObjectId("54de8bc8022ff38bbf5e0532"),
"name" : "apple"
},
{
"_id" : ObjectId("54de8bba022ff38bbf5e0531"),
"name" : "choco"
}
]
}
],
"ok" : 1
}
As for async, typically you'd do something like this:
db.collection.aggregate(thePipeLineAbove, function(err, results) {
// handle err
if (err) {
// deal with it
} else {
console.log(results);
}
});
But that depends a bit on your MongoDB driver.
You could expand this even if you have deeper hierarchy structure.
This has nothing to do with NodeJS, it's your data structure that matters.
refer to my answer to this question, the first part is about how to implement it efficiently.
I want to update nested array in Mongo DB (using Node.js). I am able to get the array index location.
How can I update same ? I am facing some problem while using escape character in $set
Here is what I am doing :
testCollection.update({
"uniqueID": someID,
"topLevelObject.innerObjectValue": innerObjectVal
}, {
$set: {
'array.' + outerArrayIndex + '.value': updatedValue,
}
}, function(err, result) {
if (err) {
console.log("Error occurred while updating db info");
}
}
);
It's hard to tell what the problem is because you have not included an example document or shown an error message or what goes wrong. Assuming your document looks like
{
"_id" : 0,
"array" : [{ "value" : 2 }, { "value" : 6 }]
}
then your above query should work, e.g.
db.test.update({ "_id" : 0 }, { "$set" : { "array.1.value" : 906 } })
will modify the document to
{
"_id" : 0,
"array" : [{ "value" : 2 }, { "value" : 906 }]
}
I omitted the other query condition because it isn't necessary with a unique id specified - perhaps the condition isn't matching any documents?
If you document looks like
{
"_id" : 0,
"array" : [2, 6]
}
then you don't need the .value in the update query:
db.test.update({ "_id" : 0 }, { "$set" : { "array.1" : 906 } })
I'd also check that the string concatenation with the variable outerArrayIndex is producing the correct field path.
I have a collection which shows a list of users with their favorite movies.
Here is a sample dataset ...
{
"_id" : ObjectId("545c08dcc4d2b8a0243dd4db"),
"mail" : "mickey#mouse.com",
"name" : "Mickey Mouse",
"favorite_movies" : [
{
"name" : "The Green Mile",
"Year" : "1992"
},
{
"name" : "Raging Bull",
"Year" : "1980"
}
],
"watched_movies" : [
{
"name" : "The Green Mile",
"Year" : "1992"
},
{
"name" : "Jaws",
"Year" : "1976"
}
]
}
Now given _id 545c08dcc4d2b8a0243dd4db and a movie
{
"name" : "InterStellar",
"Year" : "2014"
}
and if I need to add this to the watched_movies, in Node.js/MongoDB, I believe the only way is to
Find the document using Find
Do a findAndModify on the found document by appending to the watched_movies array.
Step #2 is based on example here
http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html
Is there a better way to do this ? Specifically can I avoid the step#1 ?
Here is how I'm doing step#2.
But I'm forced to do step#1 to get the "watched_movies" element and then append the new movie to it to construct the movielist
//try to update
collection.findAndModify(
{'_id':new BSON.ObjectID(id)}, //query
[['_id','asc']], //sort order
{$set: {"watched_movies": movielist}}, //replacement
{new: true}, //options
function(err, newObject){
if(err) {
console.warn(err.message);
} else {
console.log("Updated !! " + JSON.stringify(newObject));
res.send(object);
}
});
I am also open to suggestions on improving this schema design.
You can do this with a single findAnyModify call by using the $push or $addToSet array operator to directly add the new movie to the watched_movies array:
var movie = {
"name" : "InterStellar",
"Year" : "2014"
};
collection.findAndModify(
{'_id':new BSON.ObjectID(id)},
[['_id','asc']],
{$addToSet: {"watched_movies": movie}},
{new: true},
function(err, newObject){
if(err) {
console.warn(err.message);
} else {
console.log("Updated !! " + JSON.stringify(newObject));
res.send(newObject);
}
});