struktura agregacji
a nie .distinct()
polecenie:
db.event.aggregate([
// De-normalize the array content to separate documents
{ "$unwind": "$tags" },
// Filter the de-normalized content to remove non-matches
{ "$match": { "tags": /foo/ } },
// Group the "like" terms as the "key"
{ "$group": {
"_id": "$tags"
}}
])
Prawdopodobnie lepiej jest użyć „kotwicy” na początku wyrażenia regularnego, jeśli chodzi o „początek” ciągu. A także robiąc to $match
przed przetworzeniem $unwind
a także:
db.event.aggregate([
// Match the possible documents. Always the best approach
{ "$match": { "tags": /^foo/ } },
// De-normalize the array content to separate documents
{ "$unwind": "$tags" },
// Now "filter" the content to actual matches
{ "$match": { "tags": /^foo/ } },
// Group the "like" terms as the "key"
{ "$group": {
"_id": "$tags"
}}
])
Dzięki temu nie przetwarzasz $unwind
w każdym dokumencie w kolekcji i tylko w tych, które prawdopodobnie zawierają wartość „dopasowanych tagów” przed „przefiltrowaniem”, aby się upewnić.
Naprawdę „złożony” sposób na pewne złagodzenie dużych tablic z możliwymi dopasowaniami wymaga nieco więcej pracy, a MongoDB 2.6 lub nowszy:
db.event.aggregate([
{ "$match": { "tags": /^foo/ } },
{ "$project": {
"tags": { "$setDifference": [
{ "$map": {
"input": "$tags",
"as": "el",
"in": { "$cond": [
{ "$eq": [
{ "$substr": [ "$$el", 0, 3 ] },
"foo"
]},
"$$el",
false
]}
}},
[false]
]}
}},
{ "$unwind": "$tags" },
{ "$group": { "_id": "$tags" }}
])
Więc $map
jest ładnym "in-line" procesorem tablic, ale może zajść tylko tak daleko. $setDifference
operator neguje false
pasuje, ale ostatecznie nadal musisz przetworzyć $unwind
aby wykonać pozostałą $group
etap dla różnych wartości ogólnych.
Zaletą jest to, że tablice są teraz „redukowane” tylko do pasującego elementu „tags”. Po prostu nie używaj tego, gdy chcesz „liczyć” wystąpienia, gdy w tym samym dokumencie istnieje „wiele odrębnych” wartości. Ale znowu, są inne sposoby na poradzenie sobie z tym.