Ще трябва да използвате рамката за агрегиране. Агрегацията ще изглежда така:
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" } } }
])
Най-добрият начин да мислите за рамката за агрегиране е като поточна линия. Самата заявка е масив от JSON документи, където всеки поддокумент представлява различна стъпка в сглобката.
Стъпка 1:$match
Първата стъпка е основен филтър, като клауза WHERE в SQL. Поставяме тази стъпка първа, за да филтрираме всички документи, които не съдържат елемент на масив, съдържащ test-key
. Поставянето на това в началото на конвейера позволява на агрегирането да използва индекси.
Стъпка 2:$unwind
Втората стъпка, $unwind
, се използва за разделяне на всеки от елементите в масива "проби", за да можем да извършваме операции върху всички тях. Ако изпълните заявката само с тази стъпка, ще разберете какво имам предвид. Накратко:
{ name : "bob",
children : [ {"name" : mary}, { "name" : "sue" } ]
}
става два документа :
{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }
Стъпка 3:$match
Третата стъпка, $match
, е точен дубликат на първия $match
етап, но има друго предназначение. Тъй като следва $unwind
, този етап филтрира предишни елементи на масива, сега документи, които не отговарят на критериите за филтриране. В този случай съхраняваме само документи, където samples.key = "test-key"
Стъпка 4:$project (По избор)
Четвъртата стъпка, $project
, преструктурира документа. В този случай извадих елементите от масива, за да мога да ги препращам директно. Използвайки примера по-горе..
{ name : "bob", children : [ { "name" : mary } ] }
става
{ new_name : "bob", new_child_name : mary }
Имайте предвид, че тази стъпка е напълно незадължителна; по-късните етапи могат да бъдат завършени дори без този $project
след няколко дребни промени. В повечето случаи $project
е изцяло козметичен; агрегатите имат множество оптимизации под капака, като ръчно включване или изключване на полета в $project
не трябва да е необходимо.
Стъпка 5:$group
И накрая, $group
там се случва магията. _id
ценете това, по което ще "групирате" в света на SQL. Второто поле казва за усредняване на стойността, която дефинирах в $project
стъпка. Можете лесно да замените $sum
за извършване на сума, но операцията за броене обикновено се извършва по следния начин:my_count : { $sum : 1 }
.
Най-важното нещо, което трябва да се отбележи тук, е, че по-голямата част от извършената работа е форматирането на данните до точка, в която извършването на операцията е лесно.
Последна бележка
И накрая, исках да отбележа, че това не работете върху примерните данни, предоставени от samples.value
се дефинира като текст, който не може да се използва в аритметични операции. Ако се интересувате, промяната на типа на поле е описана тук:MongoDB Как да промените типа на поле