通过Mongo查询仅在存在时更新数组中的字段。

huangapple go评论71阅读模式
英文:

Update a field in an array only if it exists via mongo query

问题

我正在尝试更新数组中的字段,但使用 $set 会在字段不存在时添加该字段,如何避免这种情况?

以下是您的模型:

[
  {
    "config": {
      "isEnabled": false,
      "test": {
        "sub": [
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "k": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "k": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {}
            ]
          }
        ]
      }
    }
  }
]

这是我运行的查询:

db.collection.update({
  "config.isEnabled": false
},
{
  "$set": {
    "config.test.sub.$[].sub.4": {
      "b": "l"
    }
  }
})

输出结果:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "config": {
      "isEnabled": false,
      "test": {
        "sub": [
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          }
        ]
      }
    }
  }
]

但我想要达到这个结果:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "config": {
      "isEnabled": false,
      "test": {
        "sub": [
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {}
            ]
          }
        ]
      }
    }
  }
]

如果您观察模型数组中第三个元素中的最后一个元素,它不包含 k=l,因此我不想在数组的最后一个元素中设置该字段。

也就是说,在模型中,这是元素:

{
   "sub": [
    {},
    {},
    {},
    {}
   ]
}

当我运行我的查询时,它会更新该元素为:

{
   "sub": [
    {},
    {},
    {},
    {},
    {
     "b": "l"
    }
   ]
}

但我不希望它更新该元素。

您可以在Mongo Playground中找到此示例的链接:Mongo Playground For The Above Example

如果您想通过Mongoose实现此操作,也是可行的。

谢谢您的时间,我感激任何帮助。我尝试使用 addToSet 和 setOnInsert,但都不起作用,我知道可以找到文档,然后手动添加一些逻辑来适当地更新字段,然后更新文档,但我想知道是否有一种通过Mongo查询实现的方法。

英文:

I'm trying to update a field in an array, but using $set adds that field if it doesn't already exist, how to avoid that?
This is my model:

[
  {
    "config": {
      "isEnabled": false,
      "test": {
        "sub": [
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "k": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "k": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {}
            ]
          }
        ]
      }
    }
  },
]

Here's the query I'm running

db.collection.update({
  "config.isEnabled": false
},
{
  "$set": {
    "config.test.sub.$[].sub.4": {
      "b": "l"
    }
  }
})

Output:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "config": {
      "isEnabled": false,
      "test": {
        "sub": [
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          }
        ]
      }
    }
  }
]

But I want to attain this result:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "config": {
      "isEnabled": false,
      "test": {
        "sub": [
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          },
          {
            "sub": [
              {},
              {},
              {},
              {},
              {
                "b": "l"
              }
            ]
          }
        ]
      }
    }
  }
]

If you observe the last element in the third element in the array of the model, it does not contain k=l, hence I do not want to set that field in the last element of the array

i.e, in the model this is the element:

{
   "sub": [
    {},
    {},
    {},
    {}
   ]
}

When I run my query it updatea that element to:

{
   "sub": [
    {},
    {},
    {},
    {},
    {
     "b": "l"
    }
   ]
}

But I don't want it to update that element

Link to mongo playground:
Mongo Playground For The Above Example

> IF THIS CAN BE ACHIEVED IN MONGOOSE, THAT'D WORK TOO

Thanks for your time and I appriciate any help

I tried using addToSet and setOnInsert, none of those work, I know I can find the documents then manually add some logic to update the fields appropriately then update the document but I want to know if there's a way to achieve it via mongo query

答案1

得分: 0

一种选项是使用 $[<identifier>] 进行此操作:

db.collection.update(
  {"config.isEnabled": false},
  {$set: {"config.test.sub.$[item].sub.4": {"b": "l"}}},
  {arrayFilters: [{"item.sub.4": {$exists: true}}]}
)

playground示例上查看它的工作方式。

英文:

One option is to use $[&lt;identifier&gt;] for this:

db.collection.update(
  {&quot;config.isEnabled&quot;: false},
  {$set: {&quot;config.test.sub.$[item].sub.4&quot;: {&quot;b&quot;: &quot;l&quot;}}},
  {arrayFilters: [{&quot;item.sub.4&quot;: {$exists: true}}]}
)

See how it works on the playground example

huangapple
  • 本文由 发表于 2023年1月5日 23:26:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75020749.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定