Istnieje kilka sposobów na zrobienie tego, co chcesz, zależy to tylko od twojej wersji MongoDB. Wystarczy przesłać odpowiedzi powłoki. Zawartość jest w zasadzie reprezentacją JSON, która nie jest trudna do przetłumaczenia dla jednostek DBObject w Javie lub JavaScript do wykonania na serwerze, więc tak naprawdę się nie zmienia.
Pierwsze i najszybsze podejście dotyczy MongoDB 2.6 i nowszych, gdzie otrzymujesz nowe operacje na zestawach:
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 } }
])
Nowe operatory to $setIntersection
który wykonuje główną pracę, a także $ rozmiar
operator, który mierzy rozmiar tablicy i pomaga w drugim filtrowaniu. To kończy się podstawowym porównaniem „zestawów” w celu znalezienia elementów, które się przecinają.
Jeśli masz wcześniejszą wersję MongoDB, nadal jest to możliwe, ale potrzebujesz kilku dodatkowych etapów, co może nieco wpłynąć na wydajność, w zależności od dużych tablic:
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 }}
])
Lub jeśli wszystko to wydaje się być zaangażowane lub twoje tablice są wystarczająco duże, aby spowodować różnicę w wydajności, zawsze jest 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 }
}
)
Pamiętaj, że we wszystkich przypadkach $in
operator nadal pomaga zredukować wyniki, nawet jeśli nie jest to pełne dopasowanie. Innym wspólnym elementem jest sprawdzanie „rozmiaru” wyniku przecięcia w celu zmniejszenia odpowiedzi.
Wszystko jest dość łatwe do zakodowania, przekonaj szefa, aby przełączył się na MongoDB 2.6 lub nowszy, jeśli jeszcze nie jesteś tam, aby uzyskać najlepsze wyniki.