Reputation: 27
Field is added but then disappears. Here is the code from within the mongo shell:
> db.users.aggregate([{$addFields:{totalAge:{$sum:"$age"}}}])
{ "_id" : ObjectId("5acb81b53306361018814849"), "name" : "A", "age" : 1, "totalAge" : 1 }
{ "_id" : ObjectId("5acb81b5330636101881484a"), "name" : "B", "age" : 2, "totalAge" : 2 }
{ "_id" : ObjectId("5acb81b5330636101881484b"), "name" : "C", "age" : 3, "totalAge" : 3 }
> db.users.find().pretty()
{ "_id" : ObjectId("5acb81b53306361018814849"), "name" : "A", "age" : 1 }
{ "_id" : ObjectId("5acb81b5330636101881484a"), "name" : "B", "age" : 2 }
{ "_id" : ObjectId("5acb81b5330636101881484b"), "name" : "C", "age" : 3 }
Upvotes: 2
Views: 3013
Reputation: 654
Seems like you can use $merge, like:
> db.users.aggregate([{$addFields:{totalAge:{$sum:"$age"}}},{merge: "users"}])
Upvotes: 0
Reputation: 331
Nozar's answer was correct, but .save() is now deprecated.
Instead of using his/her exact answer, modify it by using .updateOne and $set.
Old/deprecated answer:
db.users
.aggregate([{$addFields:{totalAge:{$sum:"$age"}}}])
.forEach(function (x){db.users.save(x)})
New/working answer:
db.users
.aggregate([{$addFields:{totalAge:{$sum:"$age"}}}])
.forEach(function (x){db.users.updateOne({name: x.name}, {$set: {totalAge: x.totalAge}})})
Note: In my example, I'm using 'name' to filter (essentially match, in this case) the documents in 'users' collection, but you can use any unique field (e.g. _id field).
Shoutout to Nozar for leading me to the updated answer I provided, as I just used it in my project! (In my project, I used a $match pipeline stage prior to the $addFields pipeline stage, as I was just looking to do this to a single document in my collection, rather than all documents)
Upvotes: 3
Reputation: 9208
The aggregation pipeline doesn't alter the original data; what it does is to take a temporary in-memory copy of the data and perform a sequence of manipulations on it (still in-memory) and send it to the client.
It's similar to the way you can do db.collection.find().sort()
; the sorting there only changes what is being returned to the client, it doesn't change what is stored in the database.
The only exception is when you use the $out stage, which saves the result of the aggregation to another collection. You can see that, because they had to add a special type of stage to do this, that a normal aggregation does not write back to the stored data.
Upvotes: 1
Reputation: 505
Aggregation only reads data from your collection; it does not edit the collection too. The best way to think about aggregation is that you read some data and manipulate it for your immediate usage.
If you want change it in main source then you must use the update method.
Or an easier way (Not best but easy)
db.users.aggregate([{$addFields:{totalAge:{$sum:"$age"}}}]).forEach(function (x){
db.users.save(x)
})
Upvotes: 6
Reputation: 294
The reason is that, your both approach totally different.In aggregation, you have use $addFields in that query you will get a totalAge. But according to your find query, you can get specific data which you have stored in a database.Here you did not calculate totalAge.
I hope you can understand it.
Upvotes: 0