2015-02-28 2 views
0

Вот что я работаю с:

{ 
    "_id": ObjectId("53b4402ae1382335c95952d3"), 
    "created": ISODate("2014-07-02T10:23:54.245Z"), 
    "modified": ISODate("2011-11-28T10:06:25.186Z"), 
    "source": [{ 
     "instances": [{ 
      "analyst": "harry", 
      "date": ISODate("2014-07-02T10:23:54.242Z"), 
      "reference": "abb32" 
     }, 
     { 
      "analyst": "david", 
      "date": ISODate("2014-07-02T10:33:02.296Z"), 
      "reference": "can26" 
     }], 
     "name": "Apples" 
    }, 
    { 
     "instances": [{ 
      "analyst": "critsAPI", 
      "date": ISODate("2011-11-28T10:06:25.156Z"), 
      "reference": "z561c" 
     }], 
     "name": "Oranges" 
    }], 
    "releasability": [], 
} 

То, что я хотел бы это подсчет каждого документа, который имеет «даты экземпляры» в определенном диапазоне (позволяет сказать, месяц) наряду с определенным именем. Я использовал два запроса с «elemMatch» и, к сожалению, я не получаю ожидаемых результатов. Вот что я попытался с помощью elemMatch и instances.date:

collection.find(
        { 
        'source': 
         { 
         '$elemMatch' : { 
           'name':'Apples', 
           'instances.date' : {'$lte' : ISODate("2014-07-30T00:00:00Z") ,  
               '$gte' : ISODate("2014-07-01T00:00:00Z")} 
         } 
         } 
         } 
         ).count() 

Вот с вложенной elemMatch:

collection.find(
        { 
        'source': 
         { 
         '$elemMatch' : { 
           'name':'Apples', 
           'instances': { 
            '$elemMatch' : { 
             'date' : {'$lte' : ISODate("2014-07-30T00:00:00Z") ,  
               '$gte' : ISODate("2014-07-01T00:00:00Z")} 
         } 
         } 
         } 
         } 
         } 
         ).count() 

Спасибо заранее.

ответ

0

Я предполагаю, что вы получаете count() из 1, так как метод count() возвращает количество документов, а не количество элементов массива.

Чтобы получить результат 2 (на основании вышеуказанного документа), вам необходимо использовать структуру агрегации.

Пожалуйста, попробуйте что-то вроде следующего:

 
    db.coll1.aggregate([ 
     {$unwind : "$source"}, 
     {$unwind : "$source.instances"}, 
     {$match: { 
      $and: [ 
      {"source.name" : "Apples"}, 
      {"source.instances.date" : {"$lte" : ISODate("2014-07-30T00:00:00Z")}}, 
      {"source.instances.date" : {"$gte" : ISODate("2014-07-01T00:00:00Z")}} 
        ] 
     }}, 
     {$project: { 
      name1: "$source.name", 
      date1: "$source.instances.date" 
     }}, 
      {$group : {_id: "$name1", name1: {$sum:1}}} 
     ]) 
и я получаю следующее в оболочке { "result" : [ { "_id" : "Apples", "name1" : 2 } ], "ok" : 1 }

В $unwind брейках массива на отдельные документы, то $match делает выбор, то $project определяет поля результата (аналогично предложению SELECT в SQL) $group суммирует записи (похожие на «GROUP BY` в SQL)

Эти отдельные шаги в конвейере агрегации последовательно фильтруют/преобразуют результирующий набор документов.

Надежда, что помогает

+0

Зачем использовать '$ and' здесь? Общая предпосылка верна в отношении метода агрегирования, но вы, похоже, не понимаете основ операндов запроса. ** И ** условия в основном «неявные». То есть «101» для тех, кто стремится передать знания. –

+0

Большое спасибо Дэйву, это именно то, что я искал. Я не понимал, что только документ будет включен в счет. Мне понадобилось количество различных элементов массива. – user2012481

1

Моя идея заключается в использовании dot notation для доступа к элементам массива в сочетании с $and оператора для запроса «экземпляров даты» диапазона.

collection.find({ 
'source' : { 
    $elemMatch:{ 
     'name': 'Apples', 
     $and:[ {'instances.date' : {$lte : ISODate("2014-07-30T00:00:00Z")}} , 
       {'instances.date' : {$gte : ISODate("2014-07-01T00:00:00Z")}}] 
       } 
      }}) 

Надеется, что это поможет :)

Смежные вопросы