1

I am trying to edit the fields of entries in a collection. I am checking if the lastUpdated date is less then published date. If it is, then the entry is probably faulty and I need to make the lastUpdated date same as published date. I have created the following mongo query for it :-

           db.runCommand({ aggregate: "collectionNameHere",pipeline: [
                 {
                   $project: {
                     isFaulty: {$lt: ["$lastUpdated","$published"]}
                   }
                 },{
                   $match: {
                     isFaulty: true
                   }
                 },{
                   $addFields: {
                     lastUpdated: "$published"
                   }
                 }]
              })

I am able to get the list of documents which have this fault, but I am not able to update the field. The last $addFields does not seem to be working. There is no error as well. Can someone help me with this or if they can provide me a better query fro my use case.

Thanks a lot.

Ashh
  • 44,693
  • 14
  • 105
  • 132
Aakash
  • 675
  • 1
  • 9
  • 28
  • 1
    [`db.runCommand`](https://docs.mongodb.com/manual/reference/method/db.runCommand/) doesn't do what you think. It is just a helper command and doesn't update anything in the database. – Ashh Dec 14 '18 at 09:31
  • really? is it just for fetching data? the document does not appear to be clear on this. – Aakash Dec 14 '18 at 11:02
  • Yes. And you cannot update the document with the same field. Even The below answer will not work. You have to use either some iteration or the `$out` aggregation to achieve this. – Ashh Dec 14 '18 at 11:08
  • this seems a bit convoluted. Can you direct me to some documentation or tutorial when I can get hold of this? Just started writing mongo queries actually. – Aakash Dec 14 '18 at 11:27
  • Have look at this [**question**](https://stackoverflow.com/questions/3974985/update-mongodb-field-using-value-of-another-field). – Ashh Dec 14 '18 at 12:41

2 Answers2

1

You're doing a mistake by trying to update with aggreggation, what is not possible. You have to use update command to achieve your goal.

Cannot test it right now, but this should do the job :

db.collection.update({
  $expr: {
    $lt: [
      "$lastUpdated",
      "$published"
    ]
  }
},
{$set:{lastUpdated:"$published"}}
)
matthPen
  • 4,253
  • 1
  • 16
  • 16
0

It is not possible to update the document with the same field. You can use $out aggregation

db.collection.aggregate([
  { "$match": { "$expr": { "$lt": ["$lastUpdated", "$published"] }}},
  { "$addFields": { "lastUpdated": "$published" }}
])

here but it always creates a new collection as the "output" which is also not a solution here.

So, at last You have to use some iteration here to first find the document using find query and then need to update it. And with the async await now it quite easy to work this type of nested asynchronous looping.

const data = await db.collection
.find({ "$expr": { "$lt": ["$lastUpdated", "$published"] }})
.project({ lastUpdated: 1 })
.toArray()

await Promise.all(data.map(async(d) => {
  await db.collection.updateOne({ _id: d._id }, { $set: { lastUpdated: d.published }})
}))
Ashh
  • 44,693
  • 14
  • 105
  • 132
  • Hi, sorry for the late comment, I have mongodb 3.4, so $expr won't work sadly. Have been trying to find an alternative for that. also your await instructions in the top level do not have an async wrapper. It throws an error "await is only valid in async function" – Aakash Dec 21 '18 at 04:10
  • 1
    *also your await instructions in the top level do not have an async wrapper* I thought it is understood. Try with where clause see [here](https://stackoverflow.com/questions/4442453/mongodb-query-condition-on-comparing-2-fields) – Ashh Dec 21 '18 at 04:53