我有一个蒙戈文件像这样。
{
"_id" : ObjectId("50b429ba0e27b508d854483e"),
"array" : [
{
"id" : "1",
"letter" : "a"
},
{
"id" : "2",
"letter" : "b"
}
],
"tester" : "tom"
}
我希望能够用一个mongo命令插入和更新array
,而不是在find()
中使用条件,然后根据对象的存在运行insert()
和update()
。id
是我想作为选择器的项,所以如果我用以下代码更新数组:
{
"id" : "2",
"letter" : "c"
}
我必须使用$set
语句
db.soup.update({
"tester":"tom",
'array.id': '2'
}, {
$set: {
'array.$.letter': 'c'
}
})
如果我想在数组中插入一个新对象
{
"id" : "3",
"letter" : "d"
}
我必须使用$push
语句
db.soup.update({
"tester":"tom"
}, {
$push: {
'array': {
"id": "3",
"letter": "d"
}
}
})
我需要一个数组项的upsert排序。
我是否必须通过编程来完成这一操作,或者我可以通过一个mongo调用来完成这一操作?
6条答案
按热度按时间vmjh9lq91#
有了mongo 4.2 adding support for aggregation pipelines in update,我可以使用$set、$concatArrays、$ifNull和$filter在一次调用中将这些内容组合在一起。
这将替换
id
为'2'
的项,如果数组中没有其他项匹配,则将追加该项。1mrurvl12#
我自己也遇到过这个问题。我无法找到一个调用一次的解决方案,但我找到了一个调用两次的解决方案,* 当您的数组元素中有一个唯一的值时 *,首先使用
$pull
命令,它将从数组中删除元素,然后使用$push
。当文档不存在、文档存在但数组中的条目不存在以及条目存在时,这应该起作用。
同样,只有当您有一些东西(如本例中的
id
字段)在数组的元素之间应该是唯一的时,这才有效。pxq42qpu3#
我不知道像MongoDB2.2中那样有一个选项会upsert到嵌入式数组中,因此您可能必须在应用程序代码中处理这个问题。
如果您希望将嵌入式数组视为某种虚拟集合,则可能希望考虑将数组建模为单独的集合。
不能基于嵌入数组中的字段值进行upsert,但是如果嵌入文档不存在,可以使用
$addToSet
插入它:这并不完全适合按数组元素的
id
进行匹配的情况,但是如果您知道预期的当前值,这可能会很有用。shyt4zoc4#
在某些情况下,如果您可以重新构造文档以使用对象而不是数组,则可以实现嵌入式文档集的upsert。我刚刚在另一个问题上回答了这个问题,但为了方便起见,这里将对其进行修改。
示例文档如下
要向上插入
id
3且值为'c'的项,可以执行以下操作一个缺点是查询字段名(使用
$exists
查询运算符)需要扫描。您可以通过添加一个额外的数组字段来存储属性名来解决此问题。此字段可以正常索引和查询。(Keep注意
$addToSet
是O(n)。)当删除属性时,还必须将其从数组中拉出来。x4shl7ld5#
你可以使用数组过滤器选项。你可以参考这里https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-arrayfilters。
2w3rbyxf6#
这个问题来自2012年,我看了一下mongo的文档:Rob Watts在一篇评论中提到的https://docs.mongodb.com/manual/reference/method/Bulk.find.upsert,但非常稀疏。
我在这里找到了答案:https://stackoverflow.com/a/42952359/1374488