pymongo risparmio objectIds embedded, InvalidDocumentError
Domanda
Uso del driver pymongo nudo di pitone di connessione per MongoDB, perché è che utilizzando un'istanza ObjectId come la chiave per un documento incorporato genera un errore InvalidDocument?
Sto cercando di documenti collegamento mediante objectIds e cant sembrano capire perché vorrei convertirli in stringhe quando quelli creati automaticamente per il conducente sono casi 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')
In pratica gli ID collegate rappresentano i documenti che contengono le domande ei valori nel dizionario qui digitato come 'otherstuff' ad esempio rappresenterebbe risposte di questo documento individuale a quella particolare domanda.
C'è un motivo per applicare objectIds come questo non sarà codificare in BSON e poi fallisce? E 'impossibile objectIds nido all'interno dei documenti come questo a riferimento incrociato? Ho frainteso lo scopo di loro?
Soluzione
Il BSON spec dettami che le chiavi devono essere stringhe, quindi PyMongo è diritto di rifiutare questo come un documento non valido (e sarebbe indipendentemente da quale livello di ObjectId è stato utilizzato come una chiave, sia a livello superiore o in un documento incorporato). Ciò è necessario, tra l'altro, in modo che il linguaggio di query può essere ambiguo. Immagina di avere questo documento (e che si trattasse di un documento BSON valido):
{ _id: ...,
"4f0cbe6d7f40d36b24a5c4d7": true,
ObjectId("4f0cbe6d7f40d36b24a5c4d7"): false
}
E poi si è tentato di query con:
db.foo.find({"4f0cbe6d7f40d36b24a5c4d7": false})
Se questo ritorno questo documento? Nel caso in quella stringa essere auto-confezionato in un ObjectId? Come si sa quando Mongo che può essere auto-boxed, e come per disambiguare in casi come questo documento?
Una possibile soluzione alternativa al tuo problema è quello di avere una serie di documenti incorporati come:
{ answers: [
{ answer_id: ObjectId("..."), summary: "Good answer to this question" },
{ answer_id: ObjectId("..."), summary: "Bad answer to this question" }
]
}
Questa è BSON valida, e sarà anche indicizzabile in modo più efficiente. Se si aggiunge un indice su answers
, è possibile cercare in modo efficiente per corrispondenze esatte su questi documenti secondari; se si aggiunge un indice su answers.answer_id
, allora si può cercare in modo efficiente dal ObjectId della risposta che state cercando (e così via).