首页 文章

pymongo保存嵌入的objectIds,InvalidDocumentError

提问于
浏览
1

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

我试图使用objectids链接文档,似乎无法理解为什么我想将它们转换为字符串时,为驱动程序自动创建的是 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然后失败?是否无法将ObjectIds嵌套在这样的文档中进行交叉引用?我误解了他们的目的吗?

1 回答

  • 6

    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有效地搜索你正在寻找的答案(等等) .

相关问题