Chyba je, protože to již není pole poté, co $unwind
a proto již není platným argumentem pro $size
.
Zdá se, že se pokoušíte „sloučit“ několik existujících odpovědí, aniž byste pochopili, co dělají. Zde opravdu chcete $filter
a $size
db.collection.aggregate([
{ "$project": {
"total": {
"$size": {
"$filter": {
"input": "$Array",
"cond": { "$eq": [ "$$this.field1", "a" ] }
}
}
}
}}
])
Nebo „znovu vynalézt kolo“ pomocí $reduce
:
db.collection.aggregate([
{ "$project": {
"total": {
"$reduce": {
"input": "$Array",
"initialValue": 0,
"in": {
"$sum": [
"$$value",
{ "$cond": [{ "$eq": [ "$$this.field1", "a" ] }, 1, 0] }
}
}
}
}}
])
Nebo za to, co jste se snažili udělat s $unwind
, ve skutečnosti jste $group
znovu, abychom „spočítali“, kolik shod bylo:
db.collection.aggregate([
{ "$unwind": "$Array" },
{ "$match": { "Array.field1": "a" } },
{ "$group": {
"_id": "$_id",
"total": { "$sum": 1 }
}}
])
První dvě formy jsou „optimální“ pro moderní prostředí MongoDB. Konečná podoba s $unwind
a $group
je "starší" konstrukce, která skutečně nebyla pro tento typ operací nutná od MongoDB 2.6, i když s některými mírně odlišnými operátory.
V těchto prvních dvou v podstatě porovnáváme pole1
hodnotu každého prvku pole, i když je to stále pole. Oba $filter
a $reduce
jsou moderní operátory navržené pro práci s existujícím polem na místě. Stejné srovnání se provádí na každém z nich pomocí agregace $eq
operátor, který vrací booleovskou hodnotu založenou na tom, zda jsou zadané argumenty "rovné" nebo ne. V tomto případě na každý člen pole na očekávanou hodnotu "a"
.
V případě $filter
, pole ve skutečnosti zůstává nedotčené kromě prvků, které nesplňují zadanou podmínku v "cond"
jsou odstraněny z pole. Protože stále máme "pole" jako výstup, můžeme pak použít $velikost
operátor k měření počtu prvků pole, které zbyly po zpracování podmínky filtru.
$reduce
na druhé straně pracuje přes prvky pole a poskytuje výraz nad každým prvkem a uloženou hodnotu "accumulator", kterou jsme inicializovali pomocí "initialValue"
. V tomto případě stejný $eq
test se používá v rámci $cond
operátor. Toto je "ternární" nebo if/then/else
podmíněný operátor, který umožňuje, aby testovaný výraz, který vrací booleovskou hodnotu, vrátil then
hodnota, když pravda
nebo else
hodnota, když false
.
V tomto výrazu vrátíme 1
nebo 0
a poskytnout celkový výsledek sečtení této vrácené hodnoty a aktuálního "akumulátoru" "$$value"
s $sum
operátora, abyste je sečetli.
Konečný formulář byl použit $unwind
na poli. To, co to ve skutečnosti dělá, je dekonstrukce členů pole, aby se vytvořil „nový dokument“ pro každého člena pole a s ním související nadřazená pole v původním dokumentu. To efektivně "zkopíruje" hlavní dokument pro každý člen pole.
Jakmile $unwind
struktura dokumentů je změněna na „plošší“ formu. To je důvod, proč pak můžete provést následující $match
fáze potrubí k odstranění neshodných dokumentů.
Tím se dostáváme k $group
který se používá k „sloučení“ všech informací souvisejících se společným klíčem. V tomto případě je to _id
pole původního dokumentu, které bylo samozřejmě zkopírováno do každého dokumentu vytvořeného $unwind
. Když se vrátíme k tomuto „společnému klíči“ jako jedinému dokumentu, můžeme „spočítat“ zbývající „dokumenty“ extrahované z pole pomocí $sum
akumulátor.
Pokud bychom chtěli zbývající „pole“ zpět, můžete $push
a znovu sestavte pole pouze se zbývajícími členy:
{ "$group": {
"_id": "$_id",
"Array": { "$push": "$Array" },
"total": { "$sum": 1 }
}}
Ale samozřejmě namísto použití $size
v další fázi procesu můžeme jednoduše stále „počítat“, jako jsme to již udělali s $sum