Agregační rámec je pro to ideální. Zvažte spuštění následujícího kanálu, abyste získali požadovaný výsledek.
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{
"$project": {
"numberOfBooks": {
"$size": {
"$filter": {
"input": "$books",
"as": "el",
"cond": { "$eq": [ "$$el.year", 1990 ] }
}
}
}
}
}
];
db.collection.pipeline(pipeline);
Výše uvedený kanál používá nový $filter
operátor dostupný pro MongoDB 3.2 k vytvoření pole, které splňuje zadanou podmínku, tj. filtruje vnější prvky, které nesplňují kritéria. Počáteční $match
kanál je nezbytný k odfiltrování dokumentů, které se dostanou do agregačního kanálu v rané fázi jako strategie optimalizace kanálu.
velikost $
operátor, který akceptuje jeden výraz jako argument, vám pak dá počet prvků ve výsledném poli, takže máte požadovaný počet knih.
Pro alternativní řešení, které nepoužívá $ filtr
operátor nenalezený v dřívějších verzích, zvažte následující operaci kanálu:
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{
"$project": {
"numberOfBooks": {
"$size": {
"$setDifference": [
{
"$map": {
"input": "$books",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.year", 1990 ] },
"$$el",
false
]
}
}
},
[false]
]
}
}
}
}
];
db.collection.pipeline(pipeline);
$project
fáze potrubí zahrnuje přizpůsobení pole knih tak, že odstraníte dokumenty, které nemají rok 1990. To je možné prostřednictvím $setDifference
a $map
operátory.
$map
operátor v podstatě vytvoří nové pole pole, které obsahuje hodnoty jako výsledek vyhodnocené logiky v podvýrazu ke každému prvku pole. $setDifference
operátor pak vrátí sadu s prvky, které se vyskytují v první sadě, ale ne ve druhé sadě; tj. provádí relativní doplněk druhé sady vzhledem k první. V tomto případě vrátí konečné pole knih, které má prvky s rokem 1990 a následně $size
vypočítá počet prvků ve výsledném poli, čímž získáte počet knih.
Pro řešení, které používá $unwind
operátora, mějte na paměti, že (díky této zasvěcené odpovědi od @BlakesSeven v komentářích):
a jako poslední možnost spusťte následující kanál:
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{ "$unwind": "$books" },
{
"$match": { "books.year": 1990 }
},
{
"$group": {
"_id": null
"count": { "$sum": 1 }
}
}
]
db.collection.pipeline(pipeline)