Il quadro di aggregazione è l'ideale per questo. Prendi in considerazione l'esecuzione della seguente pipeline per ottenere il risultato desiderato.
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{
"$project": {
"numberOfBooks": {
"$size": {
"$filter": {
"input": "$books",
"as": "el",
"cond": { "$eq": [ "$$el.year", 1990 ] }
}
}
}
}
}
];
db.collection.pipeline(pipeline);
La pipeline di cui sopra utilizza il nuovo $filter
operatore disponibile per MongoDB 3.2 per produrre un array che soddisfa la condizione specificata, ovvero filtra gli elementi esterni che non soddisfano i criteri. L'iniziale $match
pipeline è necessario per filtrare i documenti che entrano nella pipeline di aggregazione all'inizio come strategia di ottimizzazione della pipeline.
Il $size
operatore che accetta una singola espressione come argomento, quindi ti dà il numero di elementi nell'array risultante, quindi hai il conteggio del libro desiderato.
Per una soluzione alternativa che non utilizza il $filter
operatore non trovato nelle versioni precedenti, considera la seguente operazione di pipeline:
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);
Il $project
la fase della pipeline prevede l'adattamento dell'array dei libri in modo da rimuovere i documenti che non hanno l'anno 1990. Ciò è possibile tramite il $setDifference
e $map
operatori.
Il $map
in sostanza, l'operatore crea un nuovo campo di matrice che contiene i valori come risultato della logica valutata in una sottoespressione per ciascun elemento di una matrice. Il $setDifference
l'operatore restituisce quindi un insieme con elementi che appaiono nel primo insieme ma non nel secondo insieme; cioè esegue un complemento relativo del secondo insieme rispetto al primo. In questo caso restituirà l'array di libri finale che ha elementi con l'anno 1990 e successivamente il $size
calcola il numero di elementi nell'array risultante, dandoti così il conteggio del libro.
Per una soluzione che utilizza $unwind
operatore, tenendo presente che (grazie a questa perspicace risposta di @BlakesSeven nei commenti):
e come ultima risorsa, esegui la seguente pipeline:
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{ "$unwind": "$books" },
{
"$match": { "books.year": 1990 }
},
{
"$group": {
"_id": null
"count": { "$sum": 1 }
}
}
]
db.collection.pipeline(pipeline)