rámec agregace
a ne .distinct()
příkaz:
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"
}}
])
Pravděpodobně je lepší použít "kotvu" na začátek regulárního výrazu, máte na mysli od "začátku" řetězce. A také to udělat $match
před zpracováním $unwind
také:
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"
}}
])
Tím zajistíte, že nezpracováváte $unwind
na každém dokumentu ve sbírce a pouze na těch, které případně obsahují hodnotu vašich „odpovídajících značek“, než se přesvědčíte, že je „filtrujete“.
Skutečně "složitý" způsob, jak poněkud zmírnit velká pole možnými shodami, vyžaduje trochu více práce a MongoDB 2.6 nebo vyšší:
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" }}
])
Takže $map
je pěkný "in-line" procesor polí, ale může jít jen tak daleko. $setDifference
operátor neguje false
shoduje se, ale nakonec stále musíte zpracovat $unwind
udělat zbývající $group
fázi pro odlišné hodnoty celkově.
Výhodou je, že pole jsou nyní „redukována“ pouze na prvek „tags“, který odpovídá. Jen to nepoužívejte, když chcete "počet" výskytů, když je ve stejném dokumentu "více odlišných" hodnot. Ale opět existují jiné způsoby, jak to zvládnout.