sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDb:encuentre un elemento común de dos matrices dentro de una consulta

Hay algunos enfoques para hacer lo que quiere, solo depende de su versión de MongoDB. Simplemente enviando las respuestas de shell. El contenido es básicamente una representación JSON que no es difícil de traducir para las entidades DBObject en Java, o JavaScript para ejecutarse en el servidor, por lo que realmente no cambia.

El primer y más rápido enfoque es con MongoDB 2.6 y superior, donde obtiene las nuevas operaciones establecidas:

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 } }
])

Los nuevos operadores son $setIntersection eso está haciendo el trabajo principal y también el $size operador que mide el tamaño de la matriz y ayuda para el último filtrado. Esto termina como una comparación básica de "conjuntos" para encontrar los elementos que se cruzan.

Si tiene una versión anterior de MongoDB, esto todavía es posible, pero necesita algunas etapas más y esto podría afectar un poco el rendimiento dependiendo de si tiene arreglos grandes:

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 }}
])

O si todo eso parece estar involucrado o sus matrices son lo suficientemente grandes como para marcar una diferencia en el rendimiento, entonces siempre hay mapaReduce :

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 }
   }
)

Tenga en cuenta que en todos los casos el $in El operador aún lo ayuda a reducir los resultados aunque no sea la coincidencia completa. El otro elemento común es verificar el "tamaño" del resultado de la intersección para reducir la respuesta.

Todo bastante fácil de codificar, convenza al jefe de que cambie a MongoDB 2.6 o superior si aún no lo ha hecho para obtener los mejores resultados.