Aggregeringsrammen er ideel til sådanne. Overvej at køre følgende pipeline for at få det ønskede resultat.
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{
"$project": {
"numberOfBooks": {
"$size": {
"$filter": {
"input": "$books",
"as": "el",
"cond": { "$eq": [ "$$el.year", 1990 ] }
}
}
}
}
}
];
db.collection.pipeline(pipeline);
Ovenstående pipeline bruger det nye $filter
operatør tilgængelig for MongoDB 3.2 til at producere et array, der opfylder den specificerede betingelse, dvs. den filtrerer ydre elementer, der ikke opfylder kriterierne. Den indledende $match
pipeline er nødvendig for at bortfiltrere dokumenter, der kommer ind i aggregeringspipelinen tidligt som en pipeline-optimeringsstrategi.
$size
operator, der accepterer et enkelt udtryk som argument, giver dig derefter antallet af elementer i det resulterende array, så du har dit ønskede bogantal.
For en alternativ løsning, der ikke bruger $ filter
operatør ikke fundet i tidligere versioner, overvej følgende pipeline-operation:
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);
$projekt
pipeline-stadiet indebærer tilpasning af bogarrayet, så du fjerner de dokumenter, der ikke har årstal 1990. Dette er gjort muligt gennem $setDifference
og $map
operatører.
$map
operatoren opretter i det væsentlige et nyt matrixfelt, der indeholder værdier som et resultat af den evaluerede logik i et underudtryk til hvert element i en matrix. $setDifference
operator returnerer derefter et sæt med elementer, der vises i det første sæt, men ikke i det andet sæt; dvs. udfører et relativt komplement af det andet sæt i forhold til det første. I dette tilfælde vil det returnere det endelige bogarray, der har elementer med år 1990 og efterfølgende $size
beregner antallet af elementer i det resulterende array, hvilket giver dig bogantallet.
For en løsning, der bruger $slap af
operatør, med det i tankerne (takket være dette indsigtsfulde svar fra @BlakesSeven i kommentarerne):
og som en sidste udvej skal du køre følgende pipeline:
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{ "$unwind": "$books" },
{
"$match": { "books.year": 1990 }
},
{
"$group": {
"_id": null
"count": { "$sum": 1 }
}
}
]
db.collection.pipeline(pipeline)