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

Media di un campo di un documento secondario tra i documenti in Mongo

Dovrai usare il framework di aggregazione. L'aggregazione finirà per assomigliare a questa:

db.stack.aggregate([
  { $match: { "samples.key" : "test-key" } },
  { $unwind : "$samples" },
  { $match : { "samples.key" : "test-key" } },
  { $project : { "new_key" : "$samples.key", "new_value" : "$samples.value" } },
  { $group : { `_id` : "$new_key", answer : { $avg : "$new_value" } } }
])

Il modo migliore per pensare al framework di aggregazione è come una catena di montaggio. La query stessa è una matrice di documenti JSON, in cui ogni documento secondario rappresenta un passaggio diverso nell'assembly.

Fase 1:$match

Il primo passaggio è un filtro di base, come una clausola WHERE in SQL. Inseriamo questo passaggio prima di tutto per filtrare tutti i documenti che non contengono un elemento dell'array contenente test-key . Il posizionamento all'inizio della pipeline consente all'aggregazione di utilizzare gli indici.

Fase 2:$rilassati

Il secondo passaggio, $unwind , viene utilizzato per separare ciascuno degli elementi nell'array "samples" in modo da poter eseguire operazioni su tutti loro. Se esegui la query solo con quel passaggio, vedrai cosa intendo. Per farla breve :

{ name : "bob", 
  children : [ {"name" : mary}, { "name" : "sue" } ] 
} 

diventa due documenti:

{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }

Fase 3:$match

Il terzo passaggio, $match , è un duplicato esatto del primo $match fase, ma ha uno scopo diverso. Poiché segue $unwind , questa fase filtra gli elementi dell'array precedenti, ora documenti, che non corrispondono ai criteri del filtro. In questo caso, conserviamo solo i documenti in cui samples.key = "test-key"

Fase 4:$progetto (facoltativo)

Il quarto passaggio, $project , ristruttura il documento. In questo caso, ho estratto gli elementi dall'array in modo da poterli fare riferimento direttamente. Utilizzando l'esempio sopra..

{ name : "bob", children : [ { "name" : mary } ] }

diventa

{ new_name : "bob", new_child_name : mary }

Nota che questo passaggio è del tutto facoltativo; le fasi successive potrebbero essere completate anche senza questo $project dopo alcune piccole modifiche. Nella maggior parte dei casi $project è interamente cosmetico; le aggregazioni hanno numerose ottimizzazioni nascoste in modo tale da includere o escludere manualmente i campi in un $project non dovrebbe essere necessario.

Fase 5:$gruppo

Infine, $group è dove avviene la magia. Il _id valuta ciò che "raggrupperai per" nel mondo SQL. Il secondo campo dice di fare la media sul valore che ho definito nel $project fare un passo. Puoi facilmente sostituire $sum per eseguire una somma, ma un'operazione di conteggio viene in genere eseguita nel modo seguente:my_count : { $sum : 1 } .

La cosa più importante da notare qui è che la maggior parte del lavoro svolto consiste nel formattare i dati in un punto in cui eseguire l'operazione è semplice.

Nota finale

Infine, volevo notare che ciò non lavorare sui dati di esempio forniti da samples.value è definito come testo, che non può essere utilizzato nelle operazioni aritmetiche. Se sei interessato, la modifica del tipo di un campo è descritta qui:MongoDB Come modificare il tipo di un campo