【发布时间】:2019-01-14 23:03:09
【问题描述】:
我将mongoengine 与具有EmbeddedDocumentListField 属性的Document 一起使用。
class Child(mongoengine.EmbeddedDocument):
value = mongoengine.IntField(required=True)
child_type = mongoengine.StringField(required=True, choices=["type1", "type2", "type3"], unique_with=["version"])
version = mongoengine.StringField(required=True, choices=["old", "current", "new"])
class Parent(mongoengine.Document):
children = mongoengine.EmbeddedDocumentListField(Child)
我正在以这种方式填充我的数据库:
def populate():
# for each child_type
for child_type in ["type1", "type2", "type3"]:
for parent_id, value in compute_stuff(child_type):
# create a new Child embedded document with version "new" and append it to the corresponding Parent
parent = Parent.get(parent_id)
child = Child(value=value, child_type=child_type, version="new")
parent.children.append(child)
parent.save()
update_versions(child_type)
现在,我正在努力解决的是我的 update_versions 函数。基本上,我想用当前的child_type 和“当前”版本更新每个Child 文档,并将其更改为“旧”版本。之后,通过将版本为“new”的Child 更改为版本“current”来执行相同操作。
这是我迄今为止尝试过的:
def update_versions(child_type):
# update "current" to "old"
Parent.objects(
children__version="current",
children__child_type=child_type
).update(set__children__S__version="old")
# update "new" to "current"
Parent.objects(
children__version="new",
children__child_type=child_type
).update(set__children__S__version="current")
不幸的是,更新没有正确完成,因为我正在尝试制作的child_type 上的过滤器似乎没有完成。这是我在数据库中得到的结果:
> // 1. before first populating -> OK
> db.parent.find({"_id": 1}).pretty()
{
"_id" : 1,
"children" : [ ]
}
> // 2. after first populating of type1 -> OK
> db.parent.find({"_id": 1}).pretty()
{
"_id" : 1,
"children" : [
{
"value" : 1,
"child_type": "type1",
"version": "new"
}
]
}
> // 3. after updating versions -> OK
> db.parent.find({"_id": 1}).pretty()
{
"_id" : 1,
"children" : [
{
"value" : 1,
"child_type": "type1",
"version": "current" // <- this is OK
}
]
}
> // 4. after first populating of type2 -> OK
> db.parent.find({"_id": 1}).pretty()
{
"_id" : 1,
"children" : [
{
"value" : 1,
"child_type": "type1",
"version": "current" // <- this is OK
},
{
"value" : 17,
"child_type": "type2",
"version": "new" // <- this is OK
}
]
}
> // 5. after updating versions (only "current" to "old") -> NOT OK
> db.parent.find({"_id": 1}).pretty()
{
"_id" : 1,
"children" : [
{
"value" : 1,
"child_type": "type1",
"version": "old" // <- this is NOT OK, expecting to stay "current"
},
{
"value" : 17,
"child_type": "type2",
"version": "new" // <- this is OK
}
]
}
我错过了什么?
编辑:这个查询似乎做我想要的,但这是一个原始的 Mongo 查询,我想“翻译它”以将它与 mongoengine 一起使用:
db.parent.updateMany(
{"children.child_type": "type1", "children.version": "current"},
{"$set": {"children.$[element].version": "old"}},
{arrayFilters: [{"element.child_type": "type1", "element.version": "current"}]}
)
注意:我不认为这是重复的,因为我发现的大多数问题都是关于更新特定的 EmbeddedDocument,给定它的 id。在这里,我想更新每个 EmbeddedDocument,而不对父级进行过滤。
【问题讨论】:
标签: python mongodb mongoengine