1
db.getCollection('alert').aggregate([{
        "$match":{
            "_id":{
                "$in":[]
             }
         }
    },
    {
        "$addFields":{
            "state":"RESOLVED",
            "log":{
                "$concatArrays":["$log",[{ "message": "HOT alert"}]
            }
         },
    {
        "$out":"alert"
    }
])

My mongodb version is 4.0.4 I am using above query to update alerts match with first pipeline. I don't know why after I run this query, the records not match with conditions were deleted. If match, the records is updated and don't be remove, just records not match with condition be removed.

Please check and help me. How I can keep all record not match with condition but still update match records

Ashh
  • 44,693
  • 14
  • 105
  • 132
Vũ Anh Dũng
  • 980
  • 3
  • 13
  • 32
  • Maybe check the other part of your code as well. This part seems ok – Algo7 Apr 21 '20 at 08:59
  • `$out` will replace your existing collection with the newly created collection i.e. the output from the `$out` aggregation. – Ashh Apr 21 '20 at 09:02
  • @Ashh yes, how I can merge exists colelction with newly created collection, I find out on mongo document, they had `$merge` but it support only 4.2 or later. I using 4.0.4 – Vũ Anh Dũng Apr 21 '20 at 09:05
  • You can remove your first `$match` and add the `$cond` with `$addFIelds` stage. But first let me know your condition – Ashh Apr 21 '20 at 09:09
  • @Ashh It very simple, just push an object to array `log` and set `state` to `RESOLVED` for alerts has id in array `{ $in: [ObjectId(...), ObjectId(...)]}`. – Vũ Anh Dũng Apr 21 '20 at 09:13
  • sample: I have 10 alerts with id is 1,2,3,4,5,6,7,8,9,10 I want to update alerts: 1,3,5. Push an object to log array and set state to resolved for 1,3,5 – Vũ Anh Dũng Apr 21 '20 at 09:14

1 Answers1

2

You can use $cond with $addFields stage

db.getCollection("alert").aggregate([
  {
    "$addFields": {
      "state": {
        "$cond": [{ "$in": ["$_id", [YOUR_IDS]] }, "RESOLVED", "$state"]
      },
      "log": {
        "$cond": [
          { "$in": ["$_id", [YOUR_IDS]] },
          { "$concatArrays": ["$log", [{ "message": "HOT alert" }]] },
          "$log"
        ]
      }
    }
  },
  { "$out": "alert" }
])
Ashh
  • 44,693
  • 14
  • 105
  • 132
  • But I have a question about your query. If I remove `$match` condition on first object in pipeline array, this query will run through all records and state will be updated if meet `$cond` If I don't remove `$match`, It will run only on matched records, right? – Vũ Anh Dũng Apr 21 '20 at 09:42
  • @VũAnhDũng Absolutely – Ashh Apr 21 '20 at 09:53
  • If that, if I have a large number of record. How is performance? Should I use aggregate or update – Vũ Anh Dũng Apr 21 '20 at 10:25
  • You should go with update query and if you can update the mongodb version then you can use aggregation operator with the update query – Ashh Apr 21 '20 at 10:54
  • Can you give me a link about aggregation operator with the update query? Thanks – Vũ Anh Dũng Apr 21 '20 at 13:40
  • @VũAnhDũng Here it is https://stackoverflow.com/questions/3974985/update-mongodb-field-using-value-of-another-field – Ashh Apr 21 '20 at 20:12