有几种方法可以做你想做的事,这取决于你的 MongoDB 版本。只需提交外壳响应。内容基本上是 JSON 表示,对于 Java 中的 DBObject 实体或要在服务器上执行的 JavaScript 不难翻译,因此实际上不会改变。
第一种也是最快的方法是使用 MongoDB 2.6 及更高版本,您可以获得新的集合操作:
var test = [ "t3", "t4", "t5" ];
db.collection.aggregate([
{ "$match": { "tags": {"$in": test } }},
{ "$project": {
"tagMatch": {
"$setIntersection": [
"$tags",
test
]
},
"sizeMatch": {
"$size": {
"$setIntersection": [
"$tags",
test
]
}
}
}},
{ "$match": { "sizeMatch": { "$gte": 1 } } },
{ "$project": { "tagMatch": 1 } }
])
新的运算符有$setIntersection 负责主要工作,还有$size 运算符用于测量数组大小并有助于后面的过滤。这最终作为“集合”的基本比较,以便找到相交的项目。
如果您有早期版本的 MongoDB,那么这仍然是可能的,但您需要更多阶段,这可能会影响性能,具体取决于您是否拥有大型数组:
var test = [ "t3", "t4", "t5" ];
db.collection.aggregate([
{ "$match": { "tags": {"$in": test } }},
{ "$project": {
"tags": 1,
"match": { "$const": test }
}},
{ "$unwind": "$tags" },
{ "$unwind": "$match" },
{ "$project": {
"tags": 1,
"matched": { "$eq": [ "$tags", "$match" ] }
}},
{ "$match": { "matched": true }},
{ "$group": {
"_id": "$_id",
"tagMatch": { "$push": "$tags" },
"count": { "$sum": 1 }
}}
{ "$match": { "count": { "$gte": 1 } }},
{ "$project": { "tagMatch": 1 }}
])
或者,如果所有这些似乎都涉及到,或者您的数组足够大以产生性能差异,那么总会有mapReduce:
var test = [ "t3", "t4", "t5" ];
db.collection.mapReduce(
function () {
var intersection = this.tags.filter(function(x){
return ( test.indexOf( x ) != -1 );
});
if ( intersection.length > 0 )
emit ( this._id, intersection );
},
function(){},
{
"query": { "tags": { "$in": test } },
"scope": { "test": test },
"output": { "inline": 1 }
}
)
请注意,在所有情况下,$in 运算符仍然可以帮助您减少结果,即使它不是完全匹配。另一个常见的元素是检查交集结果的“大小”以减少响应。
所有代码都非常容易编写,如果您还没有获得最佳结果,请说服老板切换到 MongoDB 2.6 或更高版本。