MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

MongoDb :Намерете общ елемент от два масива в рамките на заявка

Има няколко подхода да направите това, което искате, зависи само от вашата версия на 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 или по-нова, ако още не сте там, за най-добри резултати.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB Вложено ИЛИ/И Къде?

  2. MongoDB Актуализиране на вложен масив

  3. Каква е най-добрата практика за свързване/прекъсване на връзката с база данни?

  4. MongoDB + Elasticsearch или само Elasticsearch?

  5. MongoDB $cond