0

我有以下 Mongoengine 文档:

class MyEmbed(EmbeddedDocument):
    embedField = StringField(primary_key=True)
    varField = StringField()

class TestDoc(Document):
    myField = StringField()
    embed_list = ListField(EmbeddedDocumentField(MyEmbed))

所以我保留了一个嵌入文档的列表,如果它们不存在,我希望添加新文档。问题是,当我使用原子更新运算符add_to_set时,事情并没有按照我想要的方式进行。这就是我想要做的:

embed1 = models.MyEmbed(embedField="F1")
parent = models.TestDoc(myField="ParentField")
embed_list = []
embed_list.append(embed1)
parent.embed_list = embed_list
parent.save()

embed2 = models.MyEmbed(embedField="F1", varField="varField")
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed2)

问题是这样做之后,我在数据库中有一个包含 2 个元素的嵌入文档列表。我想要的是决定一个字段(在这种情况下为 embedField) 2 EmbeddedDocuments 是否相等,而不是考虑所有属性。我的问题是:

  • Mongoengine 决定 2 个 EmbeddedDocuments 是否相等的默认标准是什么?
  • 如何重新定义使 Mongoengine 决定 2 个 EmbeddedDocuments 何时相等的函数?

谢谢!

4

2 回答 2

3

实际检查是在 MongoDB 内部完成的,而不是mongoengine。

发送到 mongodb 的对象应该是相同的,但这就是它变得棘手的地方,因为 BSON 顺序很重要,而在带有字典的 python 中则不是。当转换为发送到 mongodb 时,mongoengine 只需传递一个字典。这是一个错误 - 所以我添加了#296并将修复 0.8

于 2013-04-26T09:20:52.223 回答
-1

请参阅https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/document.py#L51https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/base/document.py#L52

def __eq__(self, other):
    if isinstance(other, self.__class__):
        return self._data == other._data
    return False

它比较嵌入式文档数据的字典。所以你可以重写这个方法。

如果您查看调用 QuerySet 更新(查找add_to_setaddToSet)的文档更新,您会发现 mongoengine 不会检查列表中存在的文档,只需调用mongo $addToSet 操作https ://github.com/MongoEngine/mongoengine/blob/master /mongoengine/queryset/transform.py#L156

在您的代码中,您有文档MyEmbed(embedField="F1")并尝试添加另一个文档MyEmbed(embedField="F1", varField="varField"),所以逻辑正确:它添加新文档。如果您尝试下一个代码:

embed1 = models.MyEmbed(embedField="F1")
parent = models.TestDoc(myField="ParentField")
embed_list = []
embed_list.append(embed1)
parent.embed_list = embed_list
parent.save()

embed2 = models.MyEmbed(embedField="F1", varField="varField")
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed2)

embed3 = models.MyEmbed(embedField="F1")
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed3)

embed4 = models.MyEmbed(embedField="F1", varField="varField")
TestDoc.objects(id=parent.id).update_one(add_to_set__embed_list=embed4)

你可以发现 parent 只包含embed1and embed2

因此,要解决您的问题,您可以覆盖__eq__方法并检查列表中的文档,但您必须找到更新文档列表的另一种解决方案,因为它直接调用 mongo 方法。

于 2013-04-25T07:35:33.020 回答