2016-04-29 6 views
1

Ich bin mit Meteor mit MongoDB mit einer Sammlung von Dokumenten wie folgt aus:MongoDB Indizes auf Subdokumente nicht auf Syntax der Abfrage verwendet wird

{a: 'a1', 
b: 'b1', 
c: { 
    d: 'd1', 
    e: 'e1' 
    } 
} 

Ich habe zunächst einen Index wie folgt aus: collection._ensureIndex({'c.d': 1});

Und lief Abfragen wie folgt: collection.find({c: {d: 'd1'}). Diese liefen extrem langsam und als ich mit explain() debuggte, merkte ich, dass sie den Index nicht verwendeten.

OTOH, wenn ich eine Abfrage wie folgt lautet: collection.find({'c.d': 'd1'}), dann würde Mongo den Index verwenden.

Ich habe jetzt den Index geändert, um das gesamte Filialdokument zu indizieren, d. H. collection._ensureIndex({c: 1}), und die erste Abfrage trifft jetzt den Index.

Meine Frage ist, ist das ein Fehler oder eine Funktion? Mein Eindruck war, dass in JSON die beiden Notationen gleichwertig sind, und ehrlich gesagt würde ich erwarten, dass eine Datenbank schlau genug ist, um herauszufinden, dass sich die beiden Abfragebegriffe auf das gleiche Feld beziehen und den entsprechenden Index verwenden.

Mein Problem mit der Umgehung des gesamten Filialdokuments besteht darin, dass das Filialdokument möglicherweise mehr Felder enthält, die ich nicht indiziert benötige, und es scheint suboptimal zu sein, Zeit und RAM zu verschwenden, die Indexbegriffe nicht benötigen.

Wenn dies kein Fehler ist, gibt es eine Möglichkeit, Mongo die geschachtelte Objektsyntax zu erkennen und den Index richtig zu verwenden?

Antwort

0

Ich denke, ich habe es nach dem Überprüfen der Mongo-Dokumente herausgefunden. Grundsätzlich gibt einen Unterschied in der Semantik zwischen diesen beiden. Im Wesentlichen nimmt in der ersten Form der Abfrage {c: {d: d1}} Mongo an, dass Sie das gesamte Filialdokument angeben. Wenn Sie also ein Filialdokument {c: {d: d1, e: e1}} haben, wird es nicht übereinstimmen.

OTOH, die zweite Form der Abfrage {'c.d': d1} bedeutet, dass Sie nur eine Übereinstimmung für ein Feld innerhalb des Filialdokuments angeben. Dies würde übereinstimmen, selbst wenn das Filialdokument andere Felder oder ganze Sub-Filialdokumente hat.

Dieser Unterschied erstreckt sich auf den Index. _ensureIndex({c: 1}) und _ensureIndex({'c.d': 1}) sind zwei verschiedene Indizes, und obwohl der erste das gesamte Filialdokument indiziert, wird es nicht verwendet, wenn Sie ein einzelnes Feld mit der Notation c.d abfragen.