daiyue
daiyue

Reputation: 7458

MongoDB 4.0 aggregation addFields not saving documents after using toDate

I have the following documents,

{
  "_id" : ObjectId("5b85312981c1634f59751604"),
  "date" : "0"
},

{
  "_id" : ObjectId("5b85312981c1634f59751604"),
  "date" : "20180330"
},

{
  "_id" : ObjectId("5b85312981c1634f59751604"),
  "date" : "20180402"
},

{
  "_id" : ObjectId("5b85312981c1634f59751604"),
  "date" : "20180323"
},

I tried to convert date to ISODate using $toDate in aggregation,

db.documents.aggregate( [ { "$addFields": { "received_date": { "$cond": [ {"$ne": ["$date", "0"] }, {"$toDate": "$date"}, new Date("1970-01-01") ] } } } ] )

the query executed fine, but when I

db.documents.find({})

to examine all the documents, nothing changed, I am wondering how to fix it. I am using MongoDB 4.0.6 on Linux Mint 19.1 X64.

Upvotes: 1

Views: 1845

Answers (1)

amota
amota

Reputation: 331

As they mentioned in the comments, aggregate doesn't update documents in the database directly (just an output of them).

If you'd like to permanently add a new field to documents via aggregation (aka update the documents in the database), use the following .forEach/.updateOne method:


Your example:

db.documents
    .aggregate([{"$addFields":{"received_date":{"$cond":[{"$ne":["$date","0"]}, {"$toDate": "$date"}, new Date("1970-01-01")]}}}])
    .forEach(function (x){db.documents.updateOne({_id: x._id}, {$set: {"received_date": x.received_date}})})

Since _id's value is an ObjectID(), there may be a slight modification you need to do to {_id:x._id}. If there is, let me know and I'll update it!


Another example:

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 }

db.users
    .aggregate([{$addFields:{totalAge:{$sum:"$age"}}}])
    .forEach(function (x){db.users.updateOne({name: x.name}, {$set: {totalAge: x.totalAge}})})

Being able to update collections via the aggregation pipeline seems to be quite valuable because of what you have the power to do with aggregation (e.g. what you did in your question, doing calculations based on other fields within the document, etc.). I'm newer to MongoDB so maybe updating collections via aggregation pipeline is "bad practice", but it works and it's been quite valuable for me. I wonder why it isn't more straight-forward to do?

Note: I came up with this method after discovering Nazo's now-deprecated .save() method. Shoutout to Nazo!

Upvotes: 2

Related Questions