сохранение встроенных объектных идентификаторов, InvalidDocumentError - PullRequest
1 голос
/ 11 января 2012

При использовании драйвера 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')

На практике связанные идентификаторы представляют документы, содержащие вопросы, и значения всловарь, обозначенный здесь как «прочее», например, будет представлять ответы этого отдельного документа на этот конкретный вопрос.

Есть ли причина, по которой применение таких объектов не будет кодироваться в bson, а затем не будет выполнено?Разве невозможно вложить ObjectIds в документы, подобные этому, для перекрестных ссылок?Я неправильно понял их назначение?

1 Ответ

6 голосов
/ 11 января 2012

Спецификация BSON определяет, что ключи должны быть строками, поэтому PyMongo вправе отклонить это как недопустимый документ (и будет независимо от того, на каком уровне ObjectId использовался в качестве ключа, будь то на верхний уровень или во встроенном документе). Это необходимо, помимо прочего, чтобы язык запросов был однозначным. Представьте, что у вас есть этот документ (и что это был действительный документ 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 ответа, который вы ищете (и т. д.).

...