aggregeringsramme
og ikke .distinct()
kommando:
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"
}}
])
Du er sandsynligvis bedre af at bruge et "anker" til begyndelsen af det regex, du mener fra "starten" af strengen. Og gør også dette $match
før du behandler $unwind
også:
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"
}}
])
Det sikrer, at du ikke behandler $unwind
på hvert dokument i samlingen og kun dem, der muligvis indeholder dine "matchede tags"-værdi, før du "filtrerer" for at være sikker.
Den virkelig "komplekse" måde at afbøde store arrays på med mulige matches noget kræver lidt mere arbejde, og MongoDB 2.6 eller nyere:
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" }}
])
Så $map
er en dejlig "in-line" processor af arrays, men det kan kun gå så langt. $setDifference
operator negerer false
matcher, men i sidste ende skal du stadig behandle $unwind
for at gøre den resterende $group
trin for overordnede distinkte værdier.
Fordelen her er, at arrays nu er "reduceret" til kun "tags"-elementet, der matcher. Bare lad være med at bruge dette, når du vil have en "tælling" af forekomsterne, når der er "flere forskellige" værdier i det samme dokument. Men igen, der er andre måder at håndtere det på.