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