Pymongo Saving Excedded Objectids, Invaliddocumenterror
Вопрос
Используя драйвер Pimongo, чтобы подключить 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')
На практике связанные идентификаторы представляют документы, которые содержат вопросы, и значения в словаре здесь, которые представляют собой, как «Otherstuff», например, будут представлять ответы этого отдельного документа на этот конкретный вопрос.
Есть ли причина применения объектов, подобных этому, не будет кодировать в BSON, а затем терпит неудачу? Невозможно ли гнездировать объекты в таких документах, как это, чтобы перекрестные ссылки? Я неправильно понял их цель?
Решение
А Bson Spec Диктует, что ключи должны быть строками, поэтому Pimongo прав, чтобы отвергнуть это как недопустимый документ (и независимо от того, на каком уровне объект ID использовался в качестве ключа, будь то на верхнем уровне или в встроенном документе). Это необходимо, среди прочих причин, так что язык запросов может быть однозначным. Представьте, что у вас был этот документ (и что это был действительный документ BSON):
{ _id: ...,
"4f0cbe6d7f40d36b24a5c4d7": true,
ObjectId("4f0cbe6d7f40d36b24a5c4d7"): false
}
А потом вы попытались запросить:
db.foo.find({"4f0cbe6d7f40d36b24a5c4d7": false})
Должен ли это вернуть этот документ? Должна ли эта строка быть автоматической боксами в ObjectId? Как Монго узнает, когда это может быть автоматическим боксом, и как устранение устранения устранения в таких случаях, как этот документ?
Возможное альтернативное решение вашей проблемы состоит в том, чтобы иметь множество встроенных документов, таких как:
{ 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 ответа, который вы ищете (и так далее).