MongoDB-Primärschlüssel sind dein Freund

Für alle Dokumente in einer MongoDB-Sammlung wird ein Primärschlüssel synchronisiert _id. Dieses Feld wird beim Einfügen automatisch einem Dokument zugewiesen, sodass es selten bereitgestellt werden muss. Das Interessante an dem _idFeld ist, dass es zeitbasiert ist . Das heißt, der zugrunde liegende Typ von _id, ObjectIddh ein 12-Byte-BSON-Typ, und 4 dieser Bytes repräsentieren die Sekunden seit der Unix-Epoche.

Das Besondere an dem _idFeld ist auch, dass es automatisch indiziert wird, wie Sie unten sehen können, indem Sie eine getIndexesbeliebige Sammlung aufrufen .

1 2 3 4 5 6 7 8 9 10 11 
> db.things.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.things", "name" : "_id_" } ] 

Und wie sich jeder an herkömmliche RDBMS erinnert, sind Indizes wichtig, da sie das Abrufen von Dokumenten beschleunigen können. Indizes verbrauchen jedoch Speicher und es gibt eine leichte Leistungsminderung beim Einfügen von Dokumenten, da alle entsprechenden Indizes aktualisiert werden müssen. Während Sie ernsthaft über die Verwendung von Indizes nachdenken sollten, müssen Sie daher sparsam mit deren Verwendung umgehen.

Natürlich ist die Suche nach einem Dokument _idnur dann bequem, wenn Sie es kennen . In den meisten Fällen werden Dokumente über andere Felder durchsucht, und wenn Sie über eine Zeitreihe suchen, wie zum Beispiel, werden created_atSie verwöhnt.

Stellen Sie sich eine synchronisierte Sammlung vor logs, die einfache Dokumente enthält, die verschiedene Protokollnachrichten erfassen. Ein Beispieldokument könnte folgendermaßen aussehen:

1 2 3 4 5 6 
{ "_id" : ObjectId("51c4ab6d4d6906d494460728"), "message" : "crashed, no such method exception", "type" : "crash", "created_at" : ISODate("2013-06-21T19:37:17.992Z") } 

Was wäre, wenn ich alle Protokollnachrichten für ein Datum wie heute finden wollte? Ich könnte meine Anfrage so schreiben:

1 
db.logs.find({created_at:{'$gt': new Date(2013, 5, 20)}}) 

Wenn ich eine Erklärung zu dieser Abfrage gebe, kann ich sehen, dass, da ich keinen Index aktiviert habe created_at, ein grundlegender Cursor verwendet wird und alle Dokumente in der Sammlung gescannt wurden, um mein Ergebnis abzurufen.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
> db.logs.find({created_at:{'$gt': new Date(2013, 5, 20)}}).explain() { "cursor" : "BasicCursor", "isMultiKey" : false, "n" : 2, "nscannedObjects" : 4, "nscanned" : 4, "nscannedObjectsAllPlans" : 4, "nscannedAllPlans" : 4, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 0, "nChunkSkips" : 0, "millis" : 0, "indexBounds" : { }, "server" : "ghome-computer.home:27017" } 

Wie Sie sehen können, kann die Suche über das created_atFeld ineffizient sein. Daher könnten Sie versucht sein, einen Index für dieses Feld zu erstellen. Dies würde diese bestimmte Abfrage natürlich effizienter machen. Sie würden jedoch die Kosten für einen neuen Index tragen, der mehr Speicher verbraucht und Einfügungen aufgrund einer Aktualisierung dieses neu erstellten Index etwas langsamer wären.

Wie sich herausstellt, können Sie, da das _idFeld die Unix-Epoche einbettet, genauso einfach einen Suchausdruck erstellen, ohne das created_atFeld einzuschließen. Zum Beispiel ermöglicht die MongoDB Ruby - Treiber Sie erstellen ObjectIdein ‚s aus Timewie folgt: