khung tổng hợp
chứ không phải .distinct()
lệnh:
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"
}}
])
Bạn có lẽ tốt hơn khi sử dụng một "neo" ở đầu regex là ý của bạn từ "đầu" của chuỗi. Và cũng thực hiện điều này $match
trước khi bạn xử lý $unwind
nữa:
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"
}}
])
Điều đó đảm bảo rằng bạn không xử lý $unwind
trên mọi tài liệu trong bộ sưu tập và chỉ những tài liệu có thể chứa giá trị "các thẻ phù hợp" của bạn trước khi bạn "lọc" để đảm bảo.
Cách thực sự "phức tạp" để giảm bớt phần nào các mảng lớn với các kết quả phù hợp có thể sẽ mất nhiều công hơn một chút và MongoDB 2.6 trở lên:
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" }}
])
Vì vậy, $map
là một bộ xử lý "trong dòng" tốt đẹp của các mảng nhưng nó chỉ có thể tiến xa. $setDifference
toán tử phủ định false
khớp, nhưng cuối cùng bạn vẫn cần xử lý $unwind
để thực hiện $group
còn lại giai đoạn cho các giá trị khác biệt về tổng thể.
Lợi thế ở đây là các mảng bây giờ được "giảm" chỉ còn phần tử "thẻ" phù hợp. Chỉ không sử dụng điều này khi bạn muốn "đếm" số lần xuất hiện khi có "nhiều giá trị khác biệt" trong cùng một tài liệu. Nhưng một lần nữa, có những cách khác để xử lý điều đó.