sql >> Databasteknik >  >> NoSQL >> MongoDB

Genomsnittligt ett underdokumentfält över dokument i Mongo

Du måste använda aggregeringsramverket. Aggregeringen kommer att se ut ungefär så här:

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" } } }
])

Det bästa sättet att tänka på aggregeringsramverket är som ett löpande band. Själva frågan är en uppsättning JSON-dokument, där varje underdokument representerar ett annat steg i sammansättningen.

Steg 1:$match

Det första steget är ett grundläggande filter, som en WHERE-sats i SQL. Vi placerar detta steg först för att filtrera bort alla dokument som inte innehåller ett array-element som innehåller test-key . Genom att placera detta i början av pipelinen kan aggregeringen använda index.

Steg 2:$unwind

Det andra steget, $unwind , används för att separera vart och ett av elementen i "samples"-arrayen så att vi kan utföra operationer över dem alla. Om du kör frågan med bara det steget kommer du att förstå vad jag menar. Lång historia kort:

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

blir två dokument :

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

Steg 3:$match

Det tredje steget, $match , är en exakt dubblett av den första $match skede, men har ett annat syfte. Eftersom det följer $unwind , filtrerar detta steg bort tidigare arrayelement, nu dokument, som inte matchar filterkriterierna. I det här fallet behåller vi endast dokument där samples.key = "test-key"

Steg 4:$project (valfritt)

Det fjärde steget, $project , omstrukturerar dokumentet. I det här fallet drog jag ut objekten ur arrayen så att jag kunde referera till dem direkt. Med exemplet ovan...

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

blir

{ new_name : "bob", new_child_name : mary }

Observera att detta steg är helt valfritt; senare steg skulle kunna slutföras även utan detta $project efter några mindre ändringar. I de flesta fall $project är helt kosmetisk; aggregationer har många optimeringar under huven så att manuellt inkludera eller exkludera fält i ett $project borde inte vara nödvändigt.

Steg 5:$group

Slutligen, $group det är där magin händer. _id värdesätt vad du kommer att "gruppera efter" i SQL-världen. Det andra fältet säger att medelvärde över värdet som jag definierade i $project steg. Du kan enkelt ersätta $sum för att utföra en summa, men en räkneoperation görs vanligtvis på följande sätt:my_count : { $sum : 1 } .

Det viktigaste att notera här är att majoriteten av arbetet som görs är att formatera data till en punkt där det är enkelt att utföra operationen.

Sista anmärkning

Till sist ville jag notera att detta inte skulle göra arbeta med exempeldata som tillhandahålls sedan samples.value definieras som text, som inte kan användas i aritmetiska operationer. Om du är intresserad, ändring av typ av ett fält beskrivs här:MongoDB Hur man ändrar typ av ett fält




  1. Skapa ett flerspråkigt textindex i MongoDB

  2. Varför Redis SortedSet använder Skip List istället för Balanced Tree?

  3. Hur använder man MongoDB-aggregation för paginering?

  4. Skriver du en fråga för att lägga till flera värden till en nyckel i REDIS-hashar?