MongoDB的:UPSERT子文档MongoDB的:UPSERT子文档(MongoDB: upse

2019-05-09 03:57发布

我有一个看起来类似的东西,对唯一索引文件bars.name

{ name: 'foo', bars: [ { name: 'qux', somefield: 1 } ] }

。 我想要么更新的子文档,其中{ name: 'foo', 'bars.name': 'qux' }$set: { 'bars.$.somefield': 2 }或创建一个新的子文档与{ name: 'qux', somefield: 2 }{ name: 'foo' }

是否有可能做到这一点使用与UPSERT单个查询,或将我必须发出两个独立的吗?

相关阅读: “UPSERT”嵌入文档中 (建议更改架构有子文件标识符为重点,但这是从两年前开始,如果有更好的解决方案,现在我不知道。)

Answer 1:

没有确实没有更好的解决这一点,所以也许解释。

假设你有一个适当的文件为您展示的是具有结构:

{ 
  "name": "foo", 
  "bars": [{ 
       "name": "qux", 
       "somefield": 1 
  }] 
}

如果你喜欢这款更新

db.foo.update(
    { "name": "foo", "bars.name": "qux" },
    { "$set": { "bars.$.somefield": 2 } },
    { "upsert": true }
)

然后,因为匹配的文件被发现一切都很好。 但是,如果你改变“bars.name”的价值:

db.foo.update(
    { "name": "foo", "bars.name": "xyz" },
    { "$set": { "bars.$.somefield": 2 } },
    { "upsert": true }
)

然后你会得到一个失败。 已真的在这里唯一改变的是,在MongoDB的2.6和上述错误是有点更简洁:

WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 16836,
        "errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: bars.$.somefield"
    }
})

这是在某些方面更好,但你真的不想要“UPSERT”反正。 你想要做什么元素添加到“名称”目前不存在数组。

所以,你真正想要的是“结果”,从没有“更新插入”标志的更新尝试,看看是否有文件受到影响:

db.foo.update(
    { "name": "foo", "bars.name": "xyz" },
    { "$set": { "bars.$.somefield": 2 } }
)

得到响应:

WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })

因此,当修改后的文件是0 ,那么你知道你想发出以下更新:

db.foo.update(
    { "name": "foo" },
    { "$push": { "bars": {
        "name": "xyz",
        "somefield": 2
    }}
)

实在没有其他办法可以做到正是你想要的。 由于增加的阵列是不是严格意义上的“设置”类型的操作,您不能使用$addToSet与组合“批量更新”功能的出现,让你可以“级联”你的更新请求。

在这种情况下,它好像你需要检查的结果,或以其他方式接受阅读整个文档,并检查是否更新或代码中插入一个新的数组。



Answer 2:

如果你不介意更改架构了一下,有像这样的结构:

{ "name": "foo", "bars": { "qux": { "somefield": 1 },
                           "xyz": { "somefield": 2 },
                  }
}

您可以在一个去执行你的操作。 重申嵌入文档中的“更新插入”的完整性



Answer 3:

没有一个方法来做到这一点,如果所述更新依赖于一个参考记录被更新(例如,更新X => X + 1)。 发出2个独立的命令(设置然后插入)导致无法通过因重复检查重复,因为如果你的插件被拒绝来解决竞争条件,你会失去你的更新(效果例如,x不会可以在上面的例子中适当地递增)。 将是很好,如果MongoDB的添加此功能,因为要实现嵌入式文件是一个大抽奖,MongoDB的某些应用程序的能力。



文章来源: MongoDB: upsert sub-document