Ci sono alcuni approcci per fare quello che vuoi, dipende solo dalla tua versione di MongoDB. Inviando solo le risposte della shell. Il contenuto è fondamentalmente una rappresentazione JSON che non è difficile da tradurre per le entità DBObject in Java o JavaScript da eseguire sul server in modo che non cambi davvero.
Il primo e il più veloce approccio è con MongoDB 2.6 e versioni successive, dove ottieni le nuove operazioni sugli insiemi:
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 } }
])
I nuovi operatori sono $setIntersection
che sta facendo il lavoro principale e anche il $size
operatore che misura la dimensione dell'array e aiuta per quest'ultimo filtraggio. Questo finisce come un confronto di base di "set" per trovare gli elementi che si intersecano.
Se hai una versione precedente di MongoDB, questo è ancora possibile, ma hai bisogno di alcune fasi in più e ciò potrebbe influire in qualche modo sulle prestazioni a seconda se hai array di grandi dimensioni:
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 }}
])
Oppure, se tutto ciò sembra essere coinvolto o i tuoi array sono abbastanza grandi da fare la differenza in termini di prestazioni, c'è sempre 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 }
}
)
Tieni presente che in tutti i casi $in
l'operatore aiuta comunque a ridurre i risultati anche se non è la corrispondenza completa. L'altro elemento comune è controllare la "dimensione" del risultato dell'intersezione per ridurre la risposta.
Tutto abbastanza facile da codificare, convinci il capo a passare a MongoDB 2.6 o versioni successive se non sei già lì per ottenere i migliori risultati.