Ramy agregacji są do tego idealne. Rozważ uruchomienie następującego potoku, aby uzyskać pożądany wynik.
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{
"$project": {
"numberOfBooks": {
"$size": {
"$filter": {
"input": "$books",
"as": "el",
"cond": { "$eq": [ "$$el.year", 1990 ] }
}
}
}
}
}
];
db.collection.pipeline(pipeline);
Powyższy potok używa nowego $filter
operator dostępny dla MongoDB 3.2 w celu utworzenia tablicy spełniającej określony warunek, tj. filtruje elementy zewnętrzne, które nie spełniają kryteriów. Początkowy $match
potok jest niezbędny do odfiltrowania dokumentów wchodzących do potoku agregacji wcześnie jako strategia optymalizacji potoku.
$size
operator, który akceptuje pojedyncze wyrażenie jako argument, następnie podaje liczbę elementów w wynikowej tablicy, dzięki czemu masz żądaną liczbę książek.
W przypadku alternatywnego rozwiązania, które nie korzysta z $ filtruj
operatora, którego nie znaleziono we wcześniejszych wersjach, rozważ następujące działanie potoku:
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
etap potoku polega na dopasowaniu tablicy książek, aby usunąć dokumenty, które nie mają roku 1990. Jest to możliwe dzięki $setDifference
i $map
operatorów.
$map
Operator w istocie tworzy nowe pole tablicy, które przechowuje wartości w wyniku oszacowanej logiki w podwyrażeniu do każdego elementu tablicy. $setDifference
operator następnie zwraca zestaw z elementami, które pojawiają się w pierwszym zestawie, ale nie w drugim zestawie; tj. wykonuje względne uzupełnienie drugiego zestawu względem pierwszego. W tym przypadku zwróci ostatnią tablicę książek, która zawiera elementy z rokiem 1990, a następnie $rozmiar
oblicza liczbę elementów w wynikowej tablicy, dając w ten sposób liczbę książek.
W przypadku rozwiązania, które używa $odpręż
operator, mając na uwadze, że (dzięki tej wnikliwej odpowiedzi @BlakesSeven w komentarzach):
aw ostateczności uruchom następujący potok:
pipeline = [
{
"$match": {
"name": "james",
"books.year": 1990
}
},
{ "$unwind": "$books" },
{
"$match": { "books.year": 1990 }
},
{
"$group": {
"_id": null
"count": { "$sum": 1 }
}
}
]
db.collection.pipeline(pipeline)