问题描述
所以这是我希望我的集合中的文档在结构上的样子:
So here is what I want the documents in my collection to look like structurally:
{
"_id": "123",
"systems": [
{
"_id": "1338",
"metrics": [
"TEST"
]
}
]
}
我的目标是能够对系统和/或指标在其各自的阵列中确实/不存在的任何实例执行单个更新/插入(使用 upsert=True).目前我唯一的解决方法是按如下方式更新调用:
My goal is to be able to do a single update/insert (using upsert=True) for any instance that the system and/or metric does/doesn't exist in their respective arrays. Currently my only work around is making to update calls as follows:
if not collection.find_one({"_id": "123", "systems._id": "1338"}):
collection.update(
{"_id": "123"},
{"$addToSet": {"systems": {"_id": "1338"}}},
upsert=True)
collection.update(
{"_id": "123", "systems._id": "1338"},
{"$addToSet": {"systems.$.metrics": "TEST"}},
upsert=True)
谢谢
推荐答案
如果没有包含数组的相应查询字段,您不能应用位置运算符,但您需要位置运算符知道系统数组中的索引 $addToSet {"metrics": ["TEST"]}
.您也不能基于 {"systems._id": "1338"}
进行查询,因为文档中可能还不存在该字段 {"_id": "123"}
.因此,如果我们不能将涉及相同字段的多个操作组合在一起,则不可能在单个请求中完成,但我们不能在更新.
You cannot apply the positional operator without a corresponding query field containing an array, but you need the positional operator to know the index in the systems array to $addToSet {"metrics": ["TEST"]}
. You cannot also query based on {"systems._id": "1338"}
, because this field might not exist yet in the document {"_id": "123"}
. Thus, it's not possible to do it in a single request if we cannot combine multiple operations touching the same fields, but we cannot have conflicting mods in update.
最后的希望是,如果我们有类似于 $where operator<update document 语法中的/a> 允许我们执行任意 JavaScript 来更新文档.我怀疑我们没有(也不会)有这个.
主要问题是systems
字段上的数组索引.您可以使用 _id
属性作为新索引,重新设计架构以摆脱此索引:
{
"_id": "123",
"systems": {
"1338": {
"metrics": [
"TEST"
]
}
}
}
With this change, you could do all in one operation:
db.test.update({_id: "123"}, {$addToSet: {"systems.1338.metrics": "TEST"}}, {upsert: true})
Another option is to use the following design:
{
"_id": "123",
"systems": {
"metrics": {
"1338": [
"TEST"
]
}
}
}
The best design depends on what you intend to do.
您还可以选择在您的应用程序中本地更新文档,然后将其发送回数据库,但此选项可能无法提供我认为您想要的那种原子性.
关于您当前的工作:您不需要 if
.您可以按顺序运行这两个查询.但是,如果您有多个客户端访问您的数据库,这将是不安全的.
这篇关于是否可以在同一个更新中多次使用 $addToSet?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!