A estrutura de agregação e não o
.distinct()
comando: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"
}}
])
Você provavelmente é melhor usar uma "âncora" no início da regex, quer dizer, no "início" da string. E também fazendo isso
$match
antes de processar $unwind
também: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"
}}
])
Isso garante que você não esteja processando
$unwind
em todos os documentos da coleção e apenas naqueles que possivelmente contêm seu valor de "tags correspondentes" antes de "filtrar" para ter certeza. A maneira realmente "complexa" de mitigar um pouco grandes arrays com possíveis correspondências dá um pouco mais de trabalho, e o MongoDB 2.6 ou superior:
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" }}
])
Então
$map
é um bom processador "in-line" de matrizes, mas só pode ir tão longe. O $setDifference
operador nega o false
correspondências, mas no final das contas você ainda precisa processar $unwind
para fazer o $group
restante palco para valores distintos em geral. A vantagem aqui é que os arrays agora são "reduzidos" apenas ao elemento "tags" que corresponde. Só não use isso quando quiser uma "contagem" das ocorrências quando houver "vários valores distintos" no mesmo documento. Mas, novamente, existem outras maneiras de lidar com isso.