Frage

Warum löst die Verwendung einer ObjectId-Instanz als Schlüssel für ein eingebettetes Dokument bei Verwendung des Pymongo-Treibers zum Verbinden von Python mit Mongodb einen InvalidDocument-Fehler aus?

Ich versuche, Dokumente mithilfe von Objekt-IDs zu verknüpfen, und kann anscheinend nicht verstehen, warum ich sie in Zeichenfolgen konvertieren möchte, während dies bei den automatisch für den Treiber erstellten der Fall ist ObjectId Instanzen.

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 der Praxis stellen die verknüpften IDs Dokumente dar, die Fragen enthalten, und die Werte im Wörterbuch, die hier beispielsweise als „andere Dinge“ eingegeben werden, würden die Antworten dieses einzelnen Dokuments auf diese bestimmte Frage darstellen.

Gibt es einen Grund, warum die Anwendung solcher Objekt-IDs nicht in bson kodiert wird und dann fehlschlägt?Ist es unmöglich, ObjectIds in solchen Dokumenten zu verschachteln, um Querverweise zu ermöglichen?Habe ich ihren Zweck falsch verstanden?

War es hilfreich?

Lösung

Der BSON-Spezifikation schreibt vor, dass Schlüssel Zeichenfolgen sein müssen, daher hat PyMongo Recht, dies als ungültiges Dokument abzulehnen (und das unabhängig davon, auf welcher Ebene eine ObjectId als Schlüssel verwendet wurde, ob auf der obersten Ebene oder in einem eingebetteten Dokument).Dies ist unter anderem notwendig, damit die Abfragesprache eindeutig sein kann.Stellen Sie sich vor, Sie hätten dieses Dokument (und es wäre ein gültiges BSON-Dokument):

{ _id: ...,
  "4f0cbe6d7f40d36b24a5c4d7":           true,
  ObjectId("4f0cbe6d7f40d36b24a5c4d7"): false
}

Und dann haben Sie versucht, eine Abfrage durchzuführen mit:

db.foo.find({"4f0cbe6d7f40d36b24a5c4d7": false})

Sollte dies dieses Dokument zurückgeben?Sollte diese Zeichenfolge automatisch in eine ObjectId eingepackt werden?Woher soll Mongo wissen, wann das automatisch verpackt werden kann und wie man in Fällen wie diesem Dokument eine eindeutige Unterscheidung treffen kann?

Eine mögliche alternative Lösung für Ihr Problem besteht darin, eine Reihe eingebetteter Dokumente zu haben, wie zum Beispiel:

{ answers: [
    { answer_id: ObjectId("..."), summary: "Good answer to this question" },
    { answer_id: ObjectId("..."), summary: "Bad answer to this question" }
  ]
}

Dies ist gültiges BSON und lässt sich auch effizienter indizieren.Wenn Sie einen Index hinzufügen für answers, können Sie effizient nach genauen Übereinstimmungen in diesen Filialdokumenten suchen;wenn Sie einen Index hinzufügen answers.answer_id, dann können Sie effizient nach der ObjectId der gesuchten Antwort suchen (und so weiter).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top