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

Cursore di aggregazione Mongo e conteggio

Questo forse merita una spiegazione completa per coloro che potrebbero cercarlo, aggiungendone uno per i posteri.

In particolare, ciò che viene restituito è un flusso di eventi per node.js che racchiude in modo efficace stream.Readable interfaccia con un paio di metodi convenienti. Un .count() non è uno di questi al momento e considerando l'attuale interfaccia utilizzata non avrebbe molto senso.

Simile al risultato restituito da .stream() metodo disponibile per gli oggetti cursore, un "conteggio" non avrebbe molto senso qui quando si considera l'implementazione, poiché è pensato per essere elaborato come un "flusso" in cui alla fine si raggiunge una "fine" ma altrimenti si desidera solo elaborare fino ad arrivarci.

Se hai considerato l'interfaccia "Cursore" standard del driver, ci sono alcuni validi motivi per cui il cursore di aggregazione non è lo stesso:

  1. I cursori consentono di elaborare le azioni "modificatori" prima dell'esecuzione. Questi rientrano nelle categorie di .sort() , .limit() e .skip() . Tutti questi in realtà hanno direttive controparti nel framework di aggregazione che sono specificati nella pipeline. In quanto fasi della pipeline che potrebbero apparire "ovunque" e non solo come opzione di post-elaborazione per una semplice query, non avrebbe molto senso offrire la stessa elaborazione "cursore".

  2. Altri modificatori del cursore includono speciali come .hint() , .min() e .max() che sono alterazioni della "selezione dell'indice" e dell'elaborazione. Sebbene questi possano essere utili per la pipeline di aggregazione, al momento non esiste un modo semplice per includerli nella selezione della query. Per lo più la logica del punto precedente ha la precedenza su qualsiasi punto dell'utilizzo dello stesso tipo di interfaccia per un "Cursore".

Le altre considerazioni riguardano cosa si vuole effettivamente fare con un cursore e perché si "vuole" che venga restituito. Poiché un cursore è di solito un "viaggio di sola andata", nel senso che di solito vengono elaborati solo fino al raggiungimento di una fine e in "batch" utilizzabili, si giunge a una ragionevole conclusione che il "conteggio" arriva effettivamente alla fine, quando in effetti quella "coda" è finalmente esaurita.

Sebbene sia vero che in effetti l'implementazione standard del "cursore" contiene alcuni trucchi, il motivo principale è che questo estende semplicemente un concetto di "meta" dati poiché il motore di profilazione delle query deve "scansionare" un certo numero di documenti per determinare quale articoli da restituire nel risultato.

Il framework di aggregazione gioca un po' con questo concetto. Poiché non solo ci sono gli stessi risultati che verrebbero elaborati tramite il profiler di query standard, ma ci sono anche fasi aggiuntive. Ognuna di queste fasi ha il potenziale per "modificare" il "conteggio" risultante che verrebbe effettivamente restituito nel "flusso" da elaborare.

Ancora una volta, se vuoi guardare questo da un punto di vista accademico e dire che "Certo, il motore di query dovrebbe conservare i 'metadati' per il conteggio, ma non possiamo tenere traccia di ciò che viene modificato dopo?". Questo sarebbe un argomento legittimo e operatori di pipeline come $match e $group o $unwind e possibilmente anche includendo $project e il nuovo $redact , tutto potrebbe essere considerato un caso ragionevole per tenere traccia dei "documenti elaborati" in ciascuna fase della pipeline e aggiornarli nei "metadati" che potrebbero eventualmente essere restituiti per spiegare il conteggio completo dei risultati della pipeline.

L'ultimo argomento è ragionevole, ma si consideri anche che attualmente l'implementazione di un concetto di "Cursore" per i risultati della pipeline di aggregazione è un nuovo concetto per MongoDB. Si potrebbe ragionevolmente sostenere che tutte le aspettative "ragionevoli" al primo punto di progettazione sarebbero state che la "maggior parte" dei risultati della combinazione di documenti non sarebbe stata di dimensioni restrittive per le limitazioni BSON. Ma man mano che l'uso si espande, le percezioni vengono alterate e le cose cambiano per adattarsi.

Quindi questo "potrebbe" essere modificato, ma non è così che è "attualmente" implementato. Mentre .count() su un'implementazione standard del cursore ha accesso ai "metadati" in cui viene registrato il numero scansionato, qualsiasi metodo sull'implementazione corrente comporterebbe il recupero di tutti i risultati del cursore, proprio come .itcount() fa nella shell.

Elabora gli elementi "cursore" contando sull'evento "data" ed emettendo qualcosa ( possibilmente un generatore di flusso JSON) come "conteggio" alla fine. Per qualsiasi caso d'uso che richiederebbe un conteggio "in anticipo" non sembrerebbe comunque un uso valido per un cursore, poiché sicuramente l'output sarebbe un intero documento di dimensioni ragionevoli.