我有一个像这样的mongo文件。
{
"_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调用执行此操作?
答案 0 :(得分:16)
我不知道在MongoDB 2.2中会嵌入到嵌入式数组中的选项,因此您可能需要在应用程序代码中处理此问题。
鉴于您希望将嵌入式阵列视为一种虚拟集合,您可能需要考虑将该阵列建模为单独的集合。
您无法根据嵌入数组中的字段值执行upsert,但如果嵌入文档不存在,则可以使用$addToSet
插入嵌入文档:
db.soup.update({
"tester":"tom"
}, {
$addToSet: {
'array': {
"id": "3",
"letter": "d"
}
}
})
这不符合数组元素id
匹配的确切用例,但如果您知道预期的当前值,则可能很有用。
答案 1 :(得分:15)
我自己也遇到了这个问题。我无法找到一个通话解决方案,但是当您在数组元素中有一个唯一值时,我找到了一个双调用解决方案。首先使用$pull
命令,从数组中删除元素,然后$push
。
db.soup.update({
"tester":"tom"
}, {
$pull: {
'array': {
"id": "3"
}
}
})
db.soup.update({
"tester":"tom"
}, {
$push: {
'array': {
"id": "3",
"letter": "d"
}
}
})
当文档不存在,文档存在但数组中的条目不存在以及条目存在时,这应该有效。
同样,这只有在您拥有某些内容时才有效,例如本示例中的id
字段,该内容在数组元素中应该是唯一的。
答案 2 :(得分:1)
如果您可以重新构建文档以使用对象而不是数组,则可以在某些情况下实现嵌入式文档集的upsert。我刚刚在another question上回答了这个问题,但为了方便我会在这里进行调整。
示例文档将是
{
tester: 'tom',
items: {
'1': 'a',
'2': 'b'
}
}
要使用id
3和值'c'竖立项目,您需要
db.coll.update(
{ tester: 'tom' },
{ $set: { 'items.3': 'c' } }
)
一个缺点是查询字段名称(使用$exists
查询运算符)需要扫描。您可以通过添加存储属性名称的额外数组字段来解决此问题。可以正常索引和查询该字段。 Upserts成为
db.coll.update(
{ tester: 'tom' },
{
$set: { 'items.3': 'c' },
$addToSet: { itemNames: 3 }
}
)
(请记住$addToSet
是O(n)。)删除属性时,您也必须从数组中提取它。
db.widgets.update(
{ tester: 'tom' },
{
$unset: { 'items.3': true },
$pull: { itemNames: 3 }
}
)
答案 3 :(得分:0)
嘿,您可以使用数组过滤器选项进行操作。 你可以在这里参考 https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-arrayfilters。
db.getCollection('soup').update({'tester':tom}, { $set: { "collection.$[element].letter" : 'c' } },
{
arrayFilters: [ { "element.id": 2 } ]
})
答案 4 :(得分:0)
问题是从2012年开始的。我看了一下mongo文档:https://docs.mongodb.com/manual/reference/method/Bulk.find.upsert,罗伯·沃茨在评论中提到过,但这很稀疏。