2012-09-20 1 views
21

Ho una query in mongo tale che voglio dare la preferenza al primo campo e quindi al secondo campo.Ordinamento su più campi mongo DB

dire che ho per interrogare in modo tale che

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

così ho creato il seguente indice

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

ha funzionato la scansione solo multato come molti oggetti come necessario cioè 10

Ma ora io bisogno di interrogare

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

così ho creato il seguente indice

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

ma questo porta alla scansione dell'intero documento e quando creo

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

Esamina meno il numero di documento

Voglio solo chiedere per essere chiari sull'ordinamento su più campi e quale è l'ordine da conservare quando si fa. Leggendo i documenti del mongo-DB è chiaro che il campo su cui dobbiamo eseguire l'ordinamento dovrebbe essere l'ultimo campo. Quindi questo è il caso che ho assunto nella mia query $ ne sopra. Sto facendo qualcosa di sbagliato?

risposta

25

Il MongoDB query optimizer funziona provando diversi piani per determinare quale approccio funziona meglio per una determinata query. Il piano vincente per quel modello di query viene quindi memorizzato nella cache per le prossime 1000 query o finché non si esegue un explain().

per capire quali piani di query sono stati considerati, si dovrebbe usare explain(1), ad esempio:

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

Il allPlans dettaglio mostrerà tutti i piani che sono stati confrontati.

Se si esegue una query che non è molto selettivo (per esempio, se molti record corrispondono ai suoi criteri di {category: { $ne:'A'}}), può essere più veloce per MongoDB per trovare risultati utilizzando un BasicCursor (scansione di tabella) piuttosto che la corrispondenza con un indice .

L'ordine dei campi nella query generalmente non fa la differenza per la selezione dell'indice (ci sono alcune eccezioni con le query di intervallo). L'ordine dei campi in uno ordinamento influisce sulla selezione dell'indice.Se i tuoi criteri sort() non corrispondono all'ordine dell'indice, i dati del risultato devono essere riordinati dopo l'uso dell'indice (dovresti vedere scanAndOrder:true nell'output di spiegazione se ciò accade).

Vale anche la pena notare che MongoDB utilizzerà solo one index per query (ad eccezione di $or s).

Quindi, se si sta cercando di ottimizzare la query:

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

Si vuole includere tutti e tre i campi nell'indice:

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

Cordiali saluti, se si vuole forzare una determinata query per utilizzare un indice (generalmente non necessario o consigliato), esiste un'opzione hint() che puoi provare.

+0

come fa questo risponde alla domanda? Non è ancora possibile assicurarsi di ottenere il tipo nell'ordine "rating desc, updated desc" piuttosto che "desc aggiornato, rating desc" – jobermark

+0

@jobermark Nella domanda originale il criterio di query è 'category' con un ordinamento composto di' {aggiornato: -1, valutazione: -1} '. L'ordine (e la direzione) delle chiavi nell'indice è importante; l'indice suggerito non supporta in modo efficiente una ricerca su 'content' ordinati per' {rating: -1, aggiornato: -1} '. Se si stanno manipolando i valori di ordinamento composti in un driver, utilizzare un hash/dizionario ordinato per garantire che l'ordine venga mantenuto. Per ulteriori informazioni consultare [Ordina su più campi] (https://docs.mongodb.org/manual/tutorial/sort-results-with-indexes/#sort-on-multiple-fields) nella documentazione di MongoDB. – Stennie

1

Questo è vero ma ci sono due livelli di ordinamento che hai qui da quando stai ordinando su un indice composto.

Come notato quando il primo campo dell'indice corrisponde al primo campo di ordinamento, ha funzionato e l'indice è stato visto. Tuttavia quando si lavora in senso contrario non lo fa.

Come tale dalle proprie obiezioni l'ordine da conservare è l'ordine di ricerca dei campi dal primo all'ultimo. L'analizzatore mongo può a volte spostarsi intorno ai campi per abbinare un indice, ma normalmente cercherà solo di abbinare il primo campo, se non può saltarlo.

0

provare questo codice sarà ordinare i dati prima in base al nome quindi mantenendo il 'nome' nel supporto chiave sarà ordinare 'filtro'

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