Python pymongo正在保存嵌入的ObjectId,InvalidDocumentError

Python pymongo正在保存嵌入的ObjectId,InvalidDocumentError,python,mongodb,pymongo,Python,Mongodb,Pymongo,使用pymongo驱动程序将python连接到mongodb,为什么使用ObjectId实例作为嵌入文档的键会引发InvalidDocument错误 我正在尝试使用ObjectId链接文档,但似乎无法理解,当为驱动程序自动创建的是ObjectId实例时,为什么要将它们转换为字符串 item = collection.find({'x':'foo'}) item['otherstuff'] = {pymongo.objectid.ObjectId() : 'data about this link

使用pymongo驱动程序将python连接到mongodb,为什么使用ObjectId实例作为嵌入文档的键会引发InvalidDocument错误

我正在尝试使用ObjectId链接文档,但似乎无法理解,当为驱动程序自动创建的是
ObjectId
实例时,为什么要将它们转换为字符串

item = collection.find({'x':'foo'})
item['otherstuff'] = {pymongo.objectid.ObjectId() : 'data about this link'}
collection.update({'x':'foo'}, item)
bson.errors.InvalidDocument: documents must have only string keys, key was ObjectId('4f0b5d4e764df61c67000000')
实际上,链接的ID表示包含问题的文档,而字典中键入为“otherstuff”的值(例如)表示该文档对该特定问题的响应

有没有理由像这样应用objectid不会编码到bson中然后失败?是否不可能在这样的文档中嵌套objectid以进行交叉引用?我是否误解了它们的用途?

规定键必须是字符串,因此PyMongo拒绝将其视为无效文档是正确的(无论ObjectId在什么级别用作键,无论是在顶层还是在嵌入文档中)。除其他原因外,这是必要的,以便查询语言能够明确无误。假设您拥有此文档(并且它是一个有效的BSON文档):

然后您尝试使用以下命令进行查询:

db.foo.find({"4f0cbe6d7f40d36b24a5c4d7": false})
这是否应该归还这份文件?该字符串是否应自动装箱到ObjectId中?Mongo如何知道何时可以自动装箱,以及如何在类似本文档的情况下消除歧义

您的问题的一个可能的替代解决方案是拥有一系列嵌入式文档,如:

{ answers: [
    { answer_id: ObjectId("..."), summary: "Good answer to this question" },
    { answer_id: ObjectId("..."), summary: "Bad answer to this question" }
  ]
}
这是有效的BSON,并且可以更有效地进行索引。如果在
答案
上添加索引,则可以高效地搜索这些子文档上的精确匹配项;如果您在
answers.answer\u id
上添加索引,那么您可以通过正在查找的答案的ObjectId高效地进行搜索(依此类推)。

规定键必须是字符串,因此PyMongo有权拒绝将其作为无效文档(无论ObjectId在哪个级别用作键,无论是在顶层还是在嵌入文档中)。这是必要的,除其他原因外,可以使查询语言明确无误。假设您有此文档(并且它是有效的BSON文档):

然后您尝试使用以下命令进行查询:

db.foo.find({"4f0cbe6d7f40d36b24a5c4d7": false})
这是否应该返回此文档?该字符串是否应该自动装箱到ObjectId中?Mongo如何知道何时可以自动装箱,以及在类似此文档的情况下如何消除歧义

您的问题的一个可能的替代解决方案是拥有一系列嵌入式文档,如:

{ answers: [
    { answer_id: ObjectId("..."), summary: "Good answer to this question" },
    { answer_id: ObjectId("..."), summary: "Bad answer to this question" }
  ]
}
这是有效的BSON,并且可以更高效地索引。如果您在
答案上添加索引,您可以高效地搜索这些子文档上的精确匹配项;如果您在
答案上添加索引。答案id
,则您可以按要查找答案的ObjectId高效地搜索(依此类推)