рамка за агрегиране
а не .distinct()
команда:
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"
}}
])
Вероятно е по-добре да използвате "котва" към началото на регулярния израз, ако имате предвид от "началото" на низа. И също така прави това $match
преди да обработите $unwind
както и:
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"
}}
])
Това гарантира, че не обработвате $unwind
на всеки документ в колекцията и само на тези, които вероятно съдържат стойността на вашите „съвпадащи тагове“, преди да „филтрирате“, за да сте сигурни.
Наистина „сложният“ начин за донякъде смекчаване на големи масиви с възможни съвпадения изисква малко повече работа и MongoDB 2.6 или по-нова версия:
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" }}
])
Така че $map
е хубав "вграден" процесор на масиви, но може да стигне само дотук. $setDifference
оператор отрича false
съвпада, но в крайна сметка все още трябва да обработите $unwind
за да направите оставащата $group
сцена за различни стойности като цяло.
Предимството тук е, че масивите сега са "намалени" само до елемента "tags", който съвпада. Просто не използвайте това, когато искате "брой" на случаите, когато има "множество различни" стойности в един и същи документ. Но отново има други начини за справяне с това.