MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

È possibile ordinare, raggruppare e limitare in modo efficiente in Mongo con una pipeline?

Per rispondere alla tua prima domanda:$group non preservare l'ordine. Sono aperte richieste di modifiche che evidenziano anche un po' gli sfondi ma non sembra che il prodotto verrà modificato per preservare l'ordine dei documenti di input:

In generale si possono dire due cose:in genere si desidera prima raggruppare e poi eseguire l'ordinamento. Il motivo è che l'ordinamento di meno elementi (che generalmente produce il raggruppamento) sarà più veloce dell'ordinamento di tutti i documenti di input.

In secondo luogo, MongoDB si assicurerà di ordinare nel modo più efficiente e meno possibile. La documentazione afferma:

Quindi questo codice fa il lavoro nel tuo caso:

collection.aggregate({
    $group: {
        _id: '$age',
        names: { $push: '$name' }
    }
}, {
    $sort: { 
        '_id': 1 
    }
}, {
    $limit: 10
})

MODIFICA seguendo i tuoi commenti:

concordo con quello che dici. E portando un po' più in là la tua logica, arriverei a dire:If $group era abbastanza intelligente da usare un indice, quindi non dovrebbe nemmeno richiedere un $sort fase all'inizio. Sfortunatamente, non lo è (non ancora probabilmente). Allo stato attuale delle cose, $group non utilizzerà mai un indice e non richiederà scorciatoie basate sulle fasi seguenti ($limit in questo caso). Vedi anche questo link dove qualcuno ha eseguito alcuni test di base.

Il framework di aggregazione è ancora piuttosto giovane, quindi suppongo che sia stato fatto molto lavoro per rendere la pipeline di aggregazione più intelligente e veloce.

Ci sono risposte qui su StackOverflow (ad es. qui ) dove le persone suggeriscono di utilizzare un $sort in anticipo fase per "forzare" MongoDB a utilizzare un indice in qualche modo. Ciò, tuttavia, ha rallentato notevolmente i miei test (1 milione di record della forma del tuo campione utilizzando diverse distribuzioni casuali).

Quando si tratta di prestazioni di una pipeline di aggregazione, $match le fasi all'inizio sono ciò che aiuta davvero di più. Se puoi limitare la quantità totale di record che devono passare attraverso la pipeline dall'inizio, allora è la soluzione migliore, ovviamente...;)