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);
}
});
Related
I have a dataset like this:
{
"_id" : ObjectId("5a7bee68996b551034015a15"),
"sequenceid" : 1,
"fruit" : [
{
"name" : "#APPLE",
"value" : 2
},
{
"name" : "#BANANA",
"value" : 1
},
{
"name" : "#ORANGE",
"value" : 5
}
}
want to update only Apple value i.e from 2 to 25. Expected result will be:
{
"_id" : ObjectId("5a7bee68996b551034015a15"),
"sequenceid" : 1,
"fruit" : [
{
"name" : "#APPLE",
"value" : 25
},
{
"name" : "#BANANA",
"value" : 1
},
{
"name" : "#ORANGE",
"value" : 5
}
}
I tried the code but this will replace all entry and do only one entry. My code is
db.Collection.update({'sequenceid': 1}, {$set: {'fruit' : {'name': '#APPLE', 'value': parseFloat(25)}}}, function(error, result){
if(error){
console.log('error');
} else {
console.log('success');
}
});
It can produce the result:
{
"_id" : ObjectId("5a7bee68996b551034015a15"),
"sequenceid" : 1,
"fruit" : [
{
"name" : "#APPLE",
"value" : 25
}
}//Delete all my rest entry
How I can Do this. I am a newbie on MongoDB
This will update only the first occurrence of record.For reference MongoDB - Update objects in a document's array (nested updating)
db.collection.update({ _id: ObjectId("5a7bf5586262dc7b9f3a8422") ,"fruit.name" : "#APPLE"},
{ $set:
{
"fruit.$.value" : 25
}
})
If you are writing JavaScript query then you can update like this
db.collection.find({'sequenceid': 1}).forEach(function(x){
x.fruit.forEach(function(y){
if(y.name=="#APPLE")
{
y.value = 25
}
})
db.collection.update({_id:x._id},x)
})
db.Collection.update({
_id: ObjectId("5a7bee68996b551034015a15"),
"fruit": {
$elemMatch: {
"name": "#APPLE"
}
}
}, {
$set: {
"fruit.$.value": 25
}
})
In above update operation $elemMatch operator is used to search a value in an array and in $set stage positional operator $ is used to update value of specific key belonging to an array element
I am trying to make a query for documents that have an array of objects like this. its a history of when a tag was added.
{
"added_by" : ObjectId("58d92d8b11af264b87a8f5d4"),
"tag" : ObjectId("58d92d8b11af264b87a8f5ed"),
"_id" : ObjectId("58d92d8c11af264b87a8f6d5"),
"added_at" : ISODate("2017-03-02T22:06:42.788Z")
}
I am not able to make the query on the slug just the _id
I have tried this:
var query = {
'tags.tag': {
slug: $in: ['tag-name']
}
}
Node.find(query, (err, nodes) => {
if (err) {
res.status(404)
res.send(err)
} else {
res.json(nodes);
}
}).populate(['tags.tag'])
Here is the document:
{
"_id" : ObjectId("58d92d8c11af264b87a8f6d0"),
"user_id" : ObjectId("58d92d8b11af264b87a8f5d4"),
"uid" : "-KeG2FvL0jwkHFvOautH",
"updated_at" : ISODate("2017-03-02T22:06:42.788Z"),
"created_at" : ISODate("2017-03-02T22:06:42.051Z"),
"tags" : [
{
"added_by" : ObjectId("58d92d8b11af264b87a8f5d4"),
"tag" : ObjectId("58d92d8b11af264b87a8f5ed"),
"_id" : ObjectId("58d92d8c11af264b87a8f6d5"),
"added_at" : ISODate("2017-03-02T22:06:42.788Z")
},
{
"added_by" : ObjectId("58d92d8b11af264b87a8f5d4"),
"tag" : ObjectId("58d92d8b11af264b87a8f626"),
"_id" : ObjectId("58d92d8c11af264b87a8f6d4"),
"added_at" : ISODate("2017-03-02T22:06:42.788Z")
}
],
"status" : "publish",
"description" : "some text here",
"title" : "Anna James",
"__v" : 0
}
Any thoughts?
Since you store references to tags, you need to fetch the tag by slug first:
TagsCollection.find({slug:'tag-name'}, (err, tags)...)
then filter by tag._id:
var query = {
'tags.tag': new ObjectId(tag._id)
}
or
var query = {
'tags.tag': {'$in": [new ObjectId(tag._id), ....]}
}
if you have more than 1 tag matching the slug.
Honestly, it would be way more efficient, if you store tags directly in the document, instead of storing references.
I am new to node.js.
I am having JSON object of the form
{ "_id" : ObjectId("540b03ddf1768fe562fbb715"),
"productid" : "men1",
"comments" : [ { "name" : "shiva", "text" : "Haidddsdcccccc", "_id" : ObjectId("540b03dd0570a6261e20a59e"), "date_entered" : ISODate("2014-09-06T12:53:49.658Z") },
{ "name" : "shiva", "text" : "Haidddsdcccccc", "_id" : ObjectId("540cb2be35f8145a2d296ea0"), "date_entered" : ISODate("2014-09-07T19:32:14.827Z") },
{ "name" : "shiva", "text" : "Haidddsdcccccc", "_id" : ObjectId("540cb2c335f8145a2d296ea1"), "date_entered" : ISODate("2014-09-07T19:32:19.456Z") } ] }
I want to query comments of a product after a specific time
I am using query as
var query=Product.find({"productid":obj.productid,
'comments.date_entered': {$gt: obj.timed}}, {'comments.$': 1})
I am getting only one object after the specific time i.e
{
_id: "540b03ddf1768fe562fbb715"
comments: [1]
0: {
name: "shiva"
text: "Haidddsdcccccc"
_id: "540cb2be35f8145a2d296ea0"
date_entered: "2014-09-07T19:32:14.827Z"
}
}
How to get all the comments of the product after the specified time?
Doesn't seem to be a good way to do this from what I can find out. A work-around could be doing something like this:
Product.findOne({productid: PRODUCT_ID}, {comments: 1}, function(err, product) {
var comments = product.comments.filter(function(comment) {
return comment.date_entered > DATE;
});
...
})
Doc:
{
"_id" : ObjectId("5399ba7f8035beb2d4717cc0"),
"listName" : "firstList",
"items" : [
{
"pName" : "iPad ",
"pDesc" : "iPad aiiir",
"ownerID" : ObjectId("5399b596c501732dd4d13923"),
"_id" : ObjectId("5399e2cc2d7b0349d89d2b44"),
"dateAdded" : ISODate("2014-06-12T17:26:36.282Z")
},
{
"pName" : "iPhone ",
"pDesc" : "5s",
"ownerID" : ObjectId("5399b596c501732dd4d13923"),
"_id" : ObjectId("5399e2cc2d7b0349d89d2b44"),
"dateAdded" : ISODate("2014-06-12T17:26:36.282Z")
}
]}
I want to remove an item from the "array" items without knowing the _id of the document only the id of the element,
I have this query that finds the element, it works in mongodb shell but doesn't in mongoose,
db.lists.find( {items:
{$elemMatch:{'_id':ObjectId("5399b596c501732dd4d13923")}}} ,
{"items.$":1});
Do you have an idea why ?
Can you please give me the equivalent in mongoose ?
How should I pull the item from the list knowing only its _id ?
This should do the trick:
db.lists.update(
{},
{ $pull: {"items": {"_id" :ObjectId("5399e2cc2d7b0349d89d2b44") }},
{ multi: true }})
For every document in the collection ({} means empty query), it removes every item with the provided _id (in the items array). Without the multi option, only the first document found will be affected
Ok so I found the mongoose solution to my problem thanks to Yves Amsellem.
The mongoose version of his answer is:
Lists.update(
{},
{$pull: {items: {_id: iProductId}}},
{ multi: true },
function(err, data){
console.log(err, data);
}
);
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!');
});
}