I have a DB with a set of fields f1,f2,f3, where f3 is an array. I would like to do an update operation such as this
db.collection.update ({f1:1},{$push:{f3:{$each:[f2's value],$slice:-2}}})
I searched on the internet and was not abole to find anything. I am not sure if this is even possible. Any help would be much appreciated.
EXAMPLE:
This is my set of documents:
doc1 = { name: "User1", score: "Good", History of scores: ["Good", "Bad", "Average", "Bad"] }
doc2 = { name: "User2", score: "Bad", History of scores: ["Good", "Average", "Average", "Bad"] }
doc3 = { name: "User3", score: "Good", History of scores: ["Good", "Good", "Average", "Good"] }
Now suppose we have to insert the corresponding data:
{name : "User1", score: "Good"}
I would like the document to update user1's history of scores so that doc1 becomes as follows:
doc1 = { name: "User1", score: "Good", History of scores: ["Bad", "Average", "Bad", "Good"] }
another of the same update should change doc1 to:
doc1 = { name: "User1", score: "Good", History of scores: ["Average", "Bad", "Good", "Good"] }
I hope now my question has become clearer. Thanks.
-
1it would be nice, if you add some exampleArtem Mezhenin– Artem Mezhenin2013年06月18日 07:41:34 +00:00Commented Jun 18, 2013 at 7:41
-
@artech thanks. I have added an example.Sai– Sai2013年06月18日 21:19:25 +00:00Commented Jun 18, 2013 at 21:19
2 Answers 2
Try this:
> db.c.find()
{ "_id" : ObjectId("51c156d25a334e9347b576a7"), "name" : "User1", "score" : "Good", "scores" : [ "Good", "Bad", "Average", "Bad" ] }
> db.c.update({}, {$push: {scores:{$each:['111', '222'], '$slice': -4}}})
> db.c.find()
{ "_id" : ObjectId("51c156d25a334e9347b576a7"), "name" : "User1", "score" : "Good", "scores" : [ "Average", "Bad", "111", "222" ] }
btw, I there is a problem with this kind of updates: if new object is grater then previous in size, it cause moving this object to another location on disk(e.g. you pushed "Average" and popped "Bad"). Updates "in-place" is faster, you can preallocate space for objects on first insert, like so:
> db.c.insert({ "_id" : ObjectId("51c156d25a334e9347b576a7"), "name" : "<big_tmp_string>", "score" : "<big_tmp_string>", "scores" : [ "<big_tmp_string>", "<big_tmp_string>", "<big_tmp_string>", "<big_tmp_string>" ] })
> db.c.update({ "_id" : ObjectId("51c156d25a334e9347b576a7")}, {<your_real_obj>}
1 Comment
Now that update commands can contain pipelines as of MongoDB 4.2, something like this is possible.
db.collection.updateOne({ f1: 1 }, [{
$set: {
historyOfScores: {
$concatArrays: [
"$historyOfScores",
["$score"]
]
}
}
}, {
$set: {
score: 'Good'
}
}]