Има няколко подхода да направите това, което искате, зависи само от вашата версия на MongoDB. Просто изпращам отговорите на shell. Съдържанието е основно JSON представяне, което не е трудно за превод за DBObject обекти в Java или 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
който върши основната работа, а също и $ размер
оператор, който измерва размера на масива и помага за последното филтриране. Това завършва като основно сравнение на "набори", за да се намерят елементите, които се пресичат.
Ако имате по-ранна версия на 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 или по-нова, ако още не сте там, за най-добри резултати.