4

I have a collection of documents with the "messages" array field:

{
   "id": 2,
   "messages": [
      {
         "id": 1,
         "text": "foo"
      },
      {
         "id": 2,
         "text": "bar"
      }
   ]
}

I want to update documents: add a new "message" document to the "messages" field only if "messages" doesn't contain a document with such id. For example:

{
  "id": 2,
  "text": "bllllllll"
}

should not be added

{
  "id": 3,
  "text": "foo"
}

should be added

How can I do conditional append? I know that I can filter documents in the Find part via $elemMatch operator, but it will only work for Update, with Upsert it will not work anymore.

2 Answers 2

5

To push data into array based on condition you have to use $ne in your query.

  var data = {
      "id": 3.0,
      "text": "bllllllll"
    }

suppose you want to update data into array if the id is not in that array.

db.getCollection('local').update({
    _id: ObjectId("591d6d2091b1fda9dcb6ef69"),
    "messages.id":{$ne: data.id}
    },{$push:{messages: data}})

$ne match that if data.id is present in array then it ignore the update otherwise push the data into array.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, It works, but the condition is in the "query"(filter) part of the update. If I pass upsert: true I will get a new document with this message in the messages field, I want the condition to be in the "update"(modification) part and the "query"(filter) contains only _id condition. Is it possible?
I didn't get exactly what you are trying to say.Can you elaborate with putting your code here?
1

In order to push an element in an array on certain condition matches $addToSet is a good way. If the condition matches it will push the element into the array ensuring no duplication with this push, meaning if the element being pushed is already there it will not push it. This helps in the case with upsert:true.

db.getCollection('nndemo').update({_id:ObjectId("591d9517faa19dd56df09502")},
{$addToSet:{arr:{a:2}}},{upsert:true})

1 Comment

This won't work in this example, because $addToSet will prevent the entire message from being duplicated. The question is how to prevent a message with only a matching id from being added.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.