U moet het aggregatieraamwerk gebruiken. De aggregatie ziet er ongeveer zo uit:
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" } } }
])
De beste manier om het aggregatieraamwerk te zien, is als een lopende band. De query zelf is een array van JSON-documenten, waarbij elk subdocument een andere stap in de assembly vertegenwoordigt.
Stap 1:$match
De eerste stap is een basisfilter, zoals een WHERE-clausule in SQL. We plaatsen deze stap eerst om alle documenten eruit te filteren die geen array-element bevatten dat test-key
. bevat . Door dit aan het begin van de pijplijn te plaatsen, kan de aggregatie indexen gebruiken.
Stap 2:$unwind
De tweede stap, $unwind
, wordt gebruikt voor het scheiden van elk van de elementen in de array "samples", zodat we bewerkingen op al deze elementen kunnen uitvoeren. Als je de query alleen met die stap uitvoert, zul je zien wat ik bedoel. Lang verhaal kort:
{ name : "bob",
children : [ {"name" : mary}, { "name" : "sue" } ]
}
wordt twee documenten:
{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }
Stap 3:$match
De derde stap, $match
, is een exacte kopie van de eerste $match
podium, maar heeft een ander doel. Omdat het volgt op $unwind
, filtert deze fase eerdere array-elementen, nu documenten, uit die niet voldoen aan de filtercriteria. In dit geval bewaren we alleen documenten waar samples.key = "test-key"
Stap 4:$project (optioneel)
De vierde stap, $project
, herstructureert het document. In dit geval heb ik de items uit de array gehaald, zodat ik er rechtstreeks naar kon verwijzen. Gebruik het bovenstaande voorbeeld..
{ name : "bob", children : [ { "name" : mary } ] }
wordt
{ new_name : "bob", new_child_name : mary }
Merk op dat deze stap volledig optioneel is; latere stadia zouden zelfs zonder dit $project
kunnen worden voltooid na een paar kleine veranderingen. In de meeste gevallen $project
is geheel cosmetisch; aggregaties hebben talloze optimalisaties onder de motorkap, zodat het handmatig opnemen of uitsluiten van velden in een $project
zou niet nodig moeten zijn.
Stap 5:$group
Tot slot, $group
is waar de magie gebeurt. De _id
waardeer waar u "op groepeert" in de SQL-wereld. Het tweede veld zegt het gemiddelde te nemen over de waarde die ik heb gedefinieerd in het $project
stap. U kunt eenvoudig $sum
. vervangen om een som uit te voeren, maar een telbewerking wordt meestal op de volgende manier gedaan:my_count : { $sum : 1 }
.
Het belangrijkste om hier op te merken is dat het grootste deel van het werk dat wordt gedaan bestaat uit het formatteren van de gegevens tot een punt waarop het uitvoeren van de bewerking eenvoudig is.
Laatste opmerking
Ten slotte wilde ik opmerken dat dit niet werk aan de voorbeeldgegevens die zijn verstrekt sinds samples.value
is gedefinieerd als tekst, die niet kan worden gebruikt in rekenkundige bewerkingen. Als u geïnteresseerd bent, wordt hier beschreven hoe u het type veld kunt wijzigen:MongoDB Hoe u het type veld kunt wijzigen