使用pymongo driver bare 连接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”的值将代表该单个文档对特定问题的回答。
像这样应用 objectids 不会编码到 bson 然后失败的原因是什么?像这样在文档中嵌套 ObjectId 以进行交叉引用是不可能的吗?我是否误解了它们的用途?
请您参考如下方法:
BSON spec规定键必须是字符串,因此 PyMongo 将其作为无效文档拒绝是正确的(并且无论 ObjectId 在哪个级别用作键,无论是在顶层还是在嵌入式文档中)。这是必要的,还有其他原因,以便查询语言可以是明确的。想象一下你有这个文档(并且它是一个有效的 BSON 文档):
{ _id: ...,
"4f0cbe6d7f40d36b24a5c4d7": true,
ObjectId("4f0cbe6d7f40d36b24a5c4d7"): false
}
然后你试图查询:
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 上添加索引,则可以高效地搜索这些子文档的精确匹配项;如果您在 answers.answer_id 上添加索引,则您可以通过要查找的答案的 ObjectId 进行高效搜索(依此类推)。
