Mongodb 使用正则表达式查询在数组字段上不同?
Mongodb distinct on a array field with regex query?
基本上我正在尝试在模型上实现标签功能。
> db.event.distinct("tags")
[ "bar", "foo", "foobar" ]
做一个简单的不同查询检索所有不同的标签。但是,我将如何获取与特定查询匹配的所有不同标签?举例来说,我想让所有标签匹配 foo
,然后期望得到 ["foo","foobar"]
作为结果?
以下查询是我实现此目的的失败尝试:
> db.event.distinct("tags",/foo/)
[ "bar", "foo", "foobar" ]
> db.event.distinct("tags",{tags: {$regex: 'foo'}})
[ "bar", "foo", "foobar" ]
aggregation framework 而不是 .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"
}}
])
您最好在正则表达式的开头使用 "anchor",您的意思是从字符串的 "start" 开始。并且还这样做 $match
before you process $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
集合中的每个文档,并且只处理 "filter" 之前可能包含您的 "matched tags" 值的文档。[=26] =]
真正"complex" 减轻大型阵列与可能匹配的方法需要更多的工作,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
is a nice "in-line" processor of arrays but it can only go so far. The $setDifference
运算符否定 false
匹配,但最终你仍然需要处理 $unwind
来完成剩余的 $group
阶段以获得整体不同的值。
这里的优点是数组现在 "reduced" 只匹配 "tags" 元素。当您想要在同一文档中有 "multiple distinct" 值时出现 "count" 时,请不要使用它。但同样,还有其他方法可以解决这个问题。
基本上我正在尝试在模型上实现标签功能。
> db.event.distinct("tags")
[ "bar", "foo", "foobar" ]
做一个简单的不同查询检索所有不同的标签。但是,我将如何获取与特定查询匹配的所有不同标签?举例来说,我想让所有标签匹配 foo
,然后期望得到 ["foo","foobar"]
作为结果?
以下查询是我实现此目的的失败尝试:
> db.event.distinct("tags",/foo/)
[ "bar", "foo", "foobar" ]
> db.event.distinct("tags",{tags: {$regex: 'foo'}})
[ "bar", "foo", "foobar" ]
aggregation framework 而不是 .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"
}}
])
您最好在正则表达式的开头使用 "anchor",您的意思是从字符串的 "start" 开始。并且还这样做 $match
before you process $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
集合中的每个文档,并且只处理 "filter" 之前可能包含您的 "matched tags" 值的文档。[=26] =]
真正"complex" 减轻大型阵列与可能匹配的方法需要更多的工作,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
is a nice "in-line" processor of arrays but it can only go so far. The $setDifference
运算符否定 false
匹配,但最终你仍然需要处理 $unwind
来完成剩余的 $group
阶段以获得整体不同的值。
这里的优点是数组现在 "reduced" 只匹配 "tags" 元素。当您想要在同一文档中有 "multiple distinct" 值时出现 "count" 时,请不要使用它。但同样,还有其他方法可以解决这个问题。