Magus
Magus

Reputation: 15104

$set only when the field does not exists when using the array operator in Mongodb

I need to set a default value to my documents but only when the field does not exists. My problem is that I am using an array operator.

My request is like this :

db.myCollection.updateMany({}, { $set: { 'foo.$[].bar.$[].test': 42 }})

myCollection contains the followings two documents:

{
    foo: [
        { bar: [{ a: 1 }, { a: 2, test: 18 }] },
        { bar: [{ a: 1, test: 20 }, { a: 2, test: 18 }] }
    ]
}

{
    foo: [
        { bar: [{ a: 1, test: 40 }, { a: 2, test: 18 }] },
        { bar: [{ a: 1, test: 20 }, { a: 2, test: 18 }] }
    ]
}

But if the property test exists, I don't want to overwrite it. So in my example, I only want to set the default value of one subelement (in the first document).

How can i change my request to do it?

Upvotes: 1

Views: 1074

Answers (2)

Alex Blex
Alex Blex

Reputation: 37048

Just for the sake of having an alternative to absolutely correct answer you can benefit from v4.2+ feature of using aggregation in updates. This update should do the same:

db.myCollection.updateMany({},
[
  {
    $set: {
      foo: {
        $map: {
          input: "$foo",
          as: "f",
          in: {
            $map: {
              input: "$$f.bar",
              as: "b",
              in: {
                $mergeObjects: [
                  {
                    test: 42
                  },
                  "$$b"
                ]
              }
            }
          }
        }
      }
    }
  }
])

It would be great if you can compare performance of both updates.

Upvotes: 1

turivishal
turivishal

Reputation: 36104

You can use arrayFilters,

  • create a variable b for bar is exists
  • create a variable t for test is not exists
db.myCollection.updateMany(
    {},
    { $set: { 'foo.$[b].bar.$[t].test': 42 } },
    {
        arrayFilters: [
            { "b.bar": { $exists: true } },
            { "t.test": { $exists: false } }
        ]
    }
)

Upvotes: 3

Related Questions