Les clés primaires MongoDB sont votre ami

Tous les documents d'une collection MongoDB ont une clé primaire doublée _id. Ce champ est automatiquement attribué à un document lors de l'insertion, il est donc rarement nécessaire de le fournir. Ce qui est intéressant sur le _idterrain, c'est qu'il est basé sur le temps . Autrement dit, le type sous-jacent de _id, qui est ObjectId, est un type BSON de 12 octets, et 4 de ces octets représentent les secondes depuis l'époque Unix.

La particularité du _idchamp est qu'il est automatiquement indexé comme vous pouvez le voir ci-dessous en appelant getIndexesn'importe quelle collection.

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

Et comme chacun se souvient des SGBDR traditionnels, les index sont importants car ils peuvent accélérer la recherche de documents; néanmoins, les index consomment de la mémoire et il y a une légère pénalité de performances lors de l'insertion de documents car tous les index correspondants doivent être mis à jour. Ainsi, alors que vous devriez sérieusement envisager d'utiliser les index, vous devez être économique dans leur utilisation.

Naturellement, la recherche par document _idn'est pratique que lorsque vous le connaissez . Plus souvent qu'autrement, les documents sont recherchés via d'autres champs et si vous vous retrouvez à rechercher via une série chronologique, par exemple, created_atvous allez vous régaler.

Imaginez une collection doublée logsqui contient des documents simples capturant divers messages de journal. Un exemple de document pourrait ressembler à ceci:

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") } 

Et si je voulais trouver tous les messages du journal pour une certaine date, comme aujourd'hui? Je pourrais écrire ma requête comme ceci:

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

Si je lance une explication à cette requête, je peux voir que parce que je n'ai pas d'index created_at, un curseur de base est exploité et tous les documents de la collection ont été numérisés afin de récupérer mon résultat.

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" } 

Comme vous pouvez le voir, la recherche via le created_atchamp peut être inefficace; ainsi, vous pourriez être tenté de lancer un index sur ce champ. Cela rendrait naturellement cette requête particulière plus efficace, cependant, vous encourriez le coût d'un nouvel index qui consomme plus de mémoire et les insertions seraient légèrement plus lentes en raison d'une mise à jour de cet index nouvellement créé.

En fait, comme le _idchamp intègre l'époque Unix, vous pouvez tout aussi facilement créer une expression de recherche sans inclure le created_atchamp. Par exemple, le pilote MongoDB Ruby vous permet de créer ObjectIddes fichiers Timecomme: