2012-09-20 12 views
21

Ich habe eine Abfrage in Mongo, so dass ich das erste Feld und dann das zweite Feld bevorzugen.Sortierung auf mehrere Felder mongo DB

sagen, dass ich so abzufragen haben, dass

db.col.find({category: A}).sort({updated: -1, rating: -1}).limit(10).explain() 

Also habe ich den folgenden Index

db.col.ensureIndex({category: 1, rating: -1, updated: -1}) 

Es so viele Objekte nur bestraft Scan gearbeitet wie zB 10

benötigt Aber ich jetzt muss abgefragt werden

db.col.find({category: { $ne: A}}).sort({updated: -1, rating: -1}).limit(10) 

Also habe ich den folgenden Index

db.col.ensureIndex({rating: -1, updated: -1}) 

aber dies führt zu Scannen des gesamten Dokuments und als ich

db.col.ensureIndex({ updated: -1 ,rating: -1}) 

erstellen scannt es eine geringere Anzahl von Dokumenten

Ich möchte nur fragen um Klarheit über das Sortieren auf mehreren Feldern zu haben und welche Reihenfolge dabei zu wahren ist. Durch das Lesen der Mongo-DB-Dokumente wird klar, dass das Feld, auf dem wir sortieren müssen, das letzte Feld sein sollte. Also das ist der Fall, den ich in meiner $ ne-Abfrage oben angenommen habe. Mache ich etwas falsch?

Antwort

25

Die MongoDB query optimizer funktioniert, indem Sie verschiedene Pläne ausprobieren, um zu bestimmen, welcher Ansatz am besten für eine bestimmte Abfrage funktioniert. Der gewinnende Plan für dieses Abfragemuster wird dann für die nächsten ~ 1000 Abfragen zwischengespeichert oder bis Sie eine explain() tun.

db.col.find({category:'A'}).sort({updated: -1}).explain(1) 

Die allPlans Detail zeigen alle Pläne, die verglichen wurden:

Um die Abfragepläne berücksichtigt wurden, sollten Sie explain(1), zB nutzen zu verstehen.

Wenn Sie eine Abfrage ausführen, die nicht sehr selektiv ist (z. B. wenn viele Datensätze Ihren Kriterien {category: { $ne:'A'}} entsprechen), kann es für MongoDB schneller sein, Ergebnisse mit einem BasicCursor (Tabellensuche) als mit einem Index zu finden .

Die Reihenfolge der Felder in der Abfrage macht im Allgemeinen keinen Unterschied für die Indexauswahl (es gibt ein paar Ausnahmen mit Bereichsabfragen). Die Reihenfolge der Felder in einer Sortierung wirkt sich auf die Indexauswahl aus.Wenn Ihre sort() Kriterien nicht mit der Indexreihenfolge übereinstimmen, müssen die Ergebnisdaten neu sortiert werden, nachdem der Index verwendet wurde (Sie sollten in der EXPLAIN-Ausgabe scanAndOrder:true sehen, wenn dies geschieht).

Es ist auch erwähnenswert, dass MongoDB nur one index per query (mit Ausnahme von $or s) verwenden wird.

Also, wenn Sie versuchen, die Abfrage zu optimieren:

db.col.find({category:'A'}).sort({updated: -1, rating: -1}) 

Sie werden alle drei Felder im Index enthalten sein sollen:

db.col.ensureIndex({category: 1, updated: -1, rating: -1}) 

FYI, wenn Sie eine bestimmte Abfrage erzwingen wollen Um einen Index zu verwenden (normalerweise nicht benötigt oder empfohlen), gibt es eine hint() Option, die Sie ausprobieren können.

+0

Wie beantwortet sich die Frage sortieren wird? Sie können immer noch nicht sicherstellen, dass Sie die Sortierung in der Reihenfolge "rating desc, updated desc" statt "updated desc, rating desc" erhalten. – jobermark

+0

@jobermark In der ursprünglichen Frage lautet das Abfragekriterium "category" mit einer zusammengesetzten Sortierreihenfolge von ' {aktualisiert: -1, rating: -1} '. Die Reihenfolge (und Richtung) der Schlüssel im Index ist wichtig. Der vorgeschlagene Index unterstützt eine Suche nach "content" nicht effizient, sortiert nach '{rating: -1, updated: -1}'. Wenn Sie zusammengesetzte Sortierwerte in einem Treiber bearbeiten, verwenden Sie ein geordnetes Hash/Dictionary, um sicherzustellen, dass die Reihenfolge beibehalten wird. Weitere Informationen finden Sie unter [Sortieren nach mehreren Feldern] (https://docs.mongodb.org/manual/tutorial/sort-results-with-indexes/#sort-on-multiple-fields) in der MongoDB-Dokumentation. – Stennie

1

Das ist richtig, aber es gibt zwei Ebenen der Reihenfolge, die Sie hier haben, da Sie auf einem zusammengesetzten Index sortieren.

Wie Sie festgestellt haben, wenn das erste Feld des Index mit dem ersten Feld der Sortierung übereinstimmt, funktionierte es und der Index wurde gesehen. Aber umgekehrt funktioniert es nicht.

Als solche von Ihren eigenen Beobachtungen die Reihenfolge, die beibehalten werden muss, ist Abfrage Reihenfolge der Felder von der ersten bis zur letzten. Der Mongo Analyzer kann sich manchmal um Felder herum bewegen, um einen Index zu finden, aber normalerweise versucht es einfach das erste Feld zu finden, wenn es nicht übersprungen werden kann.

0

diesen Code versuchen, es Daten zuerst auf den Namen basierend sortieren dann die ‚name‘ in Schlüsselhalter halten es ‚Filter‘

var cursor = db.collection('vc').find({ "name" : { $in: [ /cpu/, /memo/ ] }  }, { _id: 0, }).sort({ "name":1 , "filter": 1 });