sql >> Database >  >> NoSQL >> MongoDB

Gemiddeld een subdocumentveld over documenten in Mongo

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




  1. Mongodb match tekens met accenten als onderliggend teken

  2. groeperen op vragen over het verzamelen van meteoren

  3. Django Selderij krijgt taaktelling

  4. Velden hernoemen in hash voor meerdere sleutels in Redis