【问题标题】:MongoEngine document embedded in multiple documents are not the sameMongoEngine文件嵌入多个文件不一样
【发布时间】:2020-03-25 17:05:26
【问题描述】:

我有一个Contract 类,它由页面和段落列表组成。页面和段落被定义为单独的EmbeddedDocument 类。 (注意Paragraph可以跨越多个页面,所以不能是Page的子级)

每个PageParagraph 依次都有一个Line 对象列表。一行将同时出现在页面和段落中。

类的结构如下:

class Line(mongoengine.EmbeddedDocument):
    _id = mongoengine.ObjectIdField(required=True, default=ObjectId)
    text = mongoengine.StringField()

class Page(mongoengine.EmbeddedDocument):
    lines = mongoengine.ListField(mongoengine.EmbeddedDocumentField(Line))

class Paragraph(mongoengine.EmbeddedDocument):
    lines = mongoengine.ListField(mongoengine.EmbeddedDocumentField(Line))

class Contract(mongoengine.Document):
    pages = mongoengine.ListField(mongoengine.EmbeddedDocumentField(Page))
    paragraphs = mongoengine.ListField(mongoengine.EmbeddedDocumentField(Paragraph))

当我创建一个新合同并向第一页和段落添加一行时,该行是一个对象。这可以在下面看到:

# create a new contract
contract = Contract()

# create a new line
line = Line()
line.text = 'This is a test'

# create a new page and add the new line
page = Page()
page.lines.append(line)
contract.pages.append(page)

# create a new paragraph and add the new line
paragraph = Paragraph()
paragraph.lines.append(line)
contract.paragraphs.append(paragraph)

contract.save()

print(contract.pages[0].lines[0] is contract.paragraphs[0].lines[0])
>> True

print(contract.pages[0].lines[0]._id)
>> 5e7b85ebd3844b44ee1a0c8e

print(contract.paragraphs[0].lines[0]._id)
>> 5e7b85ebd3844b44ee1a0c8e

问题是我将Contract对象保存到MongoDB然后在python中再次加载后,线对象不再相同。他们仍然有相同的_id,但如果我测试是否相等,现在它返回 False:

print(contract.pages[0].lines[0] is contract.paragraphs[0].lines[0])
>> False

print(contract.pages[0].lines[0]._id)
>> 5e7b85ebd3844b44ee1a0c8e

print(contract.paragraphs[0].lines[0]._id)
>> 5e7b85ebd3844b44ee1a0c8e

这是一个问题,因为当我现在更新Page下的Line时,更改将不会反映在Paragraph中。

有没有办法确保 Python/MongoEngine 理解该行是相同的?

我正在运行 Python 3.6,mongoengine 0.19.1

【问题讨论】:

    标签: python python-3.x mongodb mongoengine


    【解决方案1】:

    如果两个变量指向同一个对象,is 将返回True,如果变量引用的对象相等,则返回==

    Is there a difference between "==" and "is"?

    改为:

    print(contract.pages[0].lines[0] == contract.paragraphs[0].lines[0])
    

    说明

    在保存 contract 实例之前,pagesparagraphs 具有相同的行实例。

    保存后,pymongo 将您的对象序列化为 BSON 结构。

    从 MongoDB 检索后,python 将从 BSON 结构中为 pagesparagraphs 创建新实例(反序列化)

    【讨论】:

    • 但这正是我的问题。我只需要一个Line 实例。所以当我从 MongoDB 检索时,它们必须指向同一个对象。
    • @RogB 实际上,对不同对象使用同一个实例是不好的做法,当您的应用程序增长时,它可能会产生意想不到的结果。所有原始类型都是不可变的,除了列表、字典、对象...... Pymongo 反序列化创建一个克隆和完全独立的对象。答案是否定的。
    • 我明白你在说什么,但在这种情况下,它们必须是同一个实例。同一行同时属于页面和段落。它们必须相同,否则当我尝试更新该行时,它只会在页面中而不是段落中更新。
    猜你喜欢
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多