1

I have documents in a MongoDB 'playground' collection following the below "schema" :

{
  "_id": ObjectId("54423b40c92f9fffb486a6d4"),

  "ProjectFileId": 1,
  "SourceLanguageId": 2,

  "TargetSegments": [
    {
      "LanguageId": 1,
      "Segment": "Something",
      "Colors": [
        1,
        2,
        3
      ],
      "Heights": [
        1,
        2,
        3
      ],
      "Widths": [
        1,
        2,
        3
      ]
    },
    {
      "LanguageId": 1,
      "Segment": "Something",
      "Colors": [
        1,
        2,
        3
      ],
      "Heights": [
        1,
        2,
        3
      ],
      "Widths": [
        1,
        2,
        3
      ]
    }
  ]
}

And the following update query:

db.playground.update({
  $and: [
    {
      "TargetSegments.Colors": {
        $exists: true
      }
    },
    {
       "ProjectFileId": 1
    },
    {
      "SourceLanguageId": 2
    },
    {
      "TargetSegments": {
        $elemMatch: {
          "LanguageId": 1
        }
      }
    }
  ]
},
{
  $set: {
    "TargetSegments.$.Segment": null,
    "TargetSegments.$.Colors": [],
    "TargetSegments.$.Widths": [],
    "TargetSegments.$.Heights": []
  }
},
false, true)

After the execution of the query the result is:

{
  "_id": ObjectId("54423b40c92f9fffb486a6d4"),

  "ProjectFileId": 1,
  "SourceLanguageId": 2,

  "TargetSegments": [
    {
      "LanguageId": 1,
      "Segment": null,
      "Colors": [],
      "Heights": [],
      "Widths": []
    },
    {
      "LanguageId": 1,
      "Segment": "Something",
      "Colors": [
        1,
        2,
        3
      ],
      "Heights": [
        1,
        2,
        3
      ],
      "Widths": [
        1,
        2,
        3
      ]
    }
  ]
}

As you can see, only the first element of the "TargetSegments" array is updated.

How can I update all the elements of the TargetSegments array in one update query?

1 Answers1

1

Its because you are using $ operator: The positional $ operator identifies an element (not multi) in an array to update without explicitly specifying the position of the element in the array. To project, or return, an array element from a read operation, see the $ projection operator.

You can use below code to do it:

db.playground.find({
  $and: [
    {
      "TargetSegments.Colors": {
        $exists: true
      }
    },
    {
       "ProjectFileId": 1
    },
    {
      "SourceLanguageId": 2
    },
    {
      "TargetSegments": {
        $elemMatch: {
          "LanguageId": 1
        }
      }
    }
  ]
}).forEach(function(item)
{
    var targets = item.TargetSegments;

    for(var index = 0; index < targets.length; index++)
    {
        var target = targets[index];
        target.Segment = null,
        target.Colors= [],
        target.Widths= [],
        target.Heights= []
    }

    db.playground.save(item);
});
Disposer
  • 6,201
  • 4
  • 31
  • 38
  • 1
    I see. But this is not a single update. Is any way of doing this in a single update operation? – Efstathios Chatzikyriakidis Oct 18 '14 at 19:12
  • MongoDB is designed without multidocument transactions, that means when you use **db.coll.update(...)** on 3 documents, you may have 0 to 3 failed update(s). In my solution there is one save() method which mongo perform save() method with single-document-transaction = you may have 0 to 3 failed update(s), same as **mongo update method** – Disposer Oct 18 '14 at 20:10
  • 1
    http://stackoverflow.com/questions/4669178/how-to-update-multiple-array-elements-in-mongodb – Disposer Oct 18 '14 at 20:42
  • The concept of "update if current" by using a version property is useful when doing only update and delete operations? – Efstathios Chatzikyriakidis Oct 18 '14 at 22:06