2016-10-16 3 views
2

В mongo как вернуть весь элемент match match из списка, если условие соответствует.Mongo query with projection

вот мои данные:

{"packages": [ 
     {"package_name" : "abc", "installed_date" : "2016-08-03"}, 
     {"package_name" : "def", "installed_date" : "2016-08-04"}, 
     {"package_name" : "ghi", "installed_date" : "2016-08-03"}, 
     ] 
    } 

Как я должен запросить, чтобы получить все словаря, который соответствовал {"installed_date" : "2016-08-03"}

Я пробовал:

db.resource.find({packages: {"$elemMatch": {installed_date: "2016-08-03"}}})

Но это дает мне все элемент массива. Я хотел бы получить Dict элемент, который соответствовал {installed_date: "2016-08-03"}

Благодарности

+0

Что происходит, когда вы добавляете пустой объект в качестве первого аргумента: db.resource.find ({}, {packages: {"$ elemMatch": {installed_date: "2016-08-03"}}}) – Brian

+0

Doesn 't выглядит как работающий, Он возвращает все остальные пакеты, которые не имеют этой даты. –

ответ

5

Try агрегации Монго:

db.resource.aggregate([ 
    {'$match':{'packages.installed_date':'2016-08-03'}}, 
    {'$unwind':'$packages'}, 
    {'$match':{'packages.installed_date':'2016-08-03'}}, 
    {'$group':{'_id':'$_id', 'packages':{'$push':'$packages'}}} 
]) 
+0

Удивительно это работает :) –

1

TRY ниже запроса: он будет работать для MongoDB 3,2

db.resource.aggregate([ 
    {$match:{"packages.installed_date" : "2016-08-03"}}, 
    { $project: { 
     package: {$filter: { 
      input: '$packages', 
      as: 'package', 
      cond: {$eq: ['$$package.installed_date', "2016-08-03"]} 
     }} 
    }} 
]) 

это будет работа без условия множественного совпадения и $ unwind

+0

Спасибо, я попробую, когда я обновлю его до 3,2 –

+0

отлично, если это возможно, тогда обновите до 3.2. есть много новых вещей и более высокая производительность. см. http://www.slideshare.net/chenghanTsai1/mongodb-300-vs-26x-vs-24x-benchmark – Sachin

2

Для решения, которое не использует оператор в $unwind, рассмотреть вопрос об использовании $map наряду $setDifference, где вы можете «фильтр» содержимое массива.

Это более эффективно, так как он работает в одном $project трубопровода, а также $unwind производит декартово произведение документов, т.е. копию каждого документа на элемент массива, который использует больше памяти (возможно крышку памяти на агрегацию трубопроводы 10% общего объема памяти) и, следовательно, занимает много времени, чтобы произвести, а также обработки документов в процессе уплощения:

db.resource.aggregate([ 
    { 
     "$project": { 
      "packages": { 
       "$setDifference": [ 
        { 
         "$map": { 
          "input": "$packages", 
          "as": "item", 
          "in": { 
           "$cond": [ 
            { "$eq": [ "$$item.installed_date", "2016-08-03" ] }, 
            "$$item", 
            false 
           ] 
          } 
         } 
        }, 
        [false] 
       ] 
      } 
     } 
    } 
]) 

в приведенном выше трубопровода, тем $map оператор в е ssence создает новое поле массива, которое содержит значения в результате оцениваемой логики в подвыражении каждому элементу массива.

Оператор $setDifference затем возвращает набор с элементами, которые отображаются в первом наборе, но не во втором наборе; т.е. выполняет относительное дополнение второго набора относительно первого. В этом случае он вернет окончательный массив packages, который имеет элементы с installed_date = "2016-08-03".