2

I have a collection that looks like this:

{
    _id: ...,
    checkins: [
        {
            id: ...,
            createdAt: 1488052032,
            ...
        },
        {
            id: ...,
            createdAt: 1488052032,
            ...
        }
    ]
}

I want to add a new element called created next to the id and createdAt attributes (inside checkins, an array of objects). And I want to do it for all the elements that doesn't have this new element.

I know how to check if an object has already an attribute in it, but I am having some problems adding the element. I am using the code below and returns me an error saying: The positional operator did not find the match needed from the query.

db.profiles.updateMany(
    {},
    {$set: {"checkins.$.created": new Date(0)}}
)

Any ideas about what I am doing wrong?

Bertrand Martel
  • 42,756
  • 16
  • 135
  • 159
newpatriks
  • 581
  • 1
  • 4
  • 23

1 Answers1

2

As the update of multiple array subdocuments is not possible as is (check this post), you can match all documents that match at least one subdocument without the created field and then update one by one the subdocuments that must be updated :

db.profiles.find({
    "checkins": {
        "$elemMatch": { "created": { "$exists": false } }
    }
}).forEach(function(doc) {

    doc.checkins.filter(function(event) {
        return !('created' in event)
    }).forEach(function(event) {

        db.profiles.update({
            "_id": doc._id,
            "checkins": {
                "$elemMatch": { "created": { "$exists": false } }
            }
        }, {
            $set: {
                "checkins.$.created": new Date(0)
            }
        });
    });
});

Note that elemMatch is used with exists is used to check if field exists. This should fixed your initial error message with your updateMany request (but your initial request won't update all your array elements)

Community
  • 1
  • 1
Bertrand Martel
  • 42,756
  • 16
  • 135
  • 159