Спецификация 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 ответа, который вы ищете (и т. д.).