2012-03-31 2 views
0

Es scheint, als ob $ oder mit einer Sortierung verwendet eine vollständige Tabelle scannen und vermeidet meine Indizes auf Titel und Schlüsselwörtern Wie kann ich es bekommen, meine beiden Indizes zu verwenden, wenn Sie eine $ oder Abfrage verwenden?

diese Abfrage verwendet sowohl den Titel und Schlüsselwörter Index

db.tasks.find({$or: [{keywords: /^japan/}, {title:/^japan/}]}) 

dies macht einen Full Table Scan und verwendet meinen Index Total_-1

db.tasks.find({$or: [{keywords: /^japan/}, {title:/^japan/}]}).sort({total:-1}) 

während Abfragen für Schlüsselwörter oder Titel mit einer Art tun Verwenden Sie die Indizes für Schlüsselwörter bzw. Titel.

db.tasks.find({title:/^japan/}).sort({total:-1}) 
db.tasks.find({keywords:/^japan/}).sort({total:-1}) 

Antwort

1

Sortierung und Indizes in Mongo sind ein komplexes Thema. Mongo hat auch einen speziellen Fehler, der verhindert, dass Sie eine Sortierung ohne Index ausführen, wenn Sie zu viele Elemente haben. Es ist also gut, dass Sie nach Indizes fragen, da eine nicht indizierte Sortierung eventuell fehlschlägt.

Es gibt eine bug in JIRA, die Ihr Problem zu decken scheint, aber es gibt einige zusätzliche Details zu berücksichtigen.

Das erste, was zu beachten sind Ihre letzten Anfragen:

db.tasks.find({title:/^japan/}).sort({total:-1}) 
db.tasks.find({keywords:/^japan/}).sort({total:-1}) 

Diese Abfragen werden schließlich scheitern, weil Sie nur die Indizierung sind auf title nicht auf title/total. Hier ist ein Skript, das das Problem demonstrieren wird.

> db.foo.ensureIndex({title:1}) 
> for(var i = 0; i < 100; i++) { db.foo.insert({title: 'japan', total: i}); } 
> db.foo.count() 
100 
> db.foo.find({title: 'japan'}).sort({total:-1}).explain() 
... uses BTreeCursor title_1 
> // Now try with one million items 
> for(var i = 0; i < 1000000; i++) { db.foo.insert({title: 'japan', total: i}); } 
> db.foo.find({title: 'japan'}).sort({total:-1}).explain() 
Sat Mar 31 05:57:41 uncaught exception: error: { 
     "$err" : "too much data for sort() with no index. add an index or specify a smaller limit", 
     "code" : 10128 
} 

Also, wenn Sie & Art auf title und total abfragen möchten, dann müssen Sie einen Index für beide in dieser Reihenfolge:

> db.foo.ensureIndex({title:1,total:1}) 
> db.foo.find({title: 'japan'}).sort({total:-1}).explain() 
{ 
     "cursor" : "BtreeCursor title_1_total_1 reverse", 
... 

Der JIRA Fehler, den ich oben für so etwas wie das ist aufgelistet folgende:

> db.foo.find({$or: [title:/^japan/, title:/^korea/]}).sort({total:-1}) 

Ihre ist etwas anders, aber es wird das gleiche Problem auftreten. Auch wenn Sie beide Indizes auf title/total und keyword/total haben, kann MongoDB Indizes nicht optimal verwenden.

+0

Wenn Sie einen Index für {total: -1, title: 1} haben und nach {total: -1, title: 1} sortieren, wird der Index dadurch effizienter? – drogon

+0

@drogon was filtern Sie? Gibt es da eine 'find()' Klausel? Der JIRA-Fehler ist sehr spezifisch für die Verwendung der '$ oder'-Klausel beim Sortieren. –

Verwandte Themen