2015-05-11 4 views
1

У меня есть коллекция со следующими документами.Mongodb Получить поддокумент и фильтр по дате

{ 
    "id":1, 
    "url":"mysite.com", 
    "views": 
    [ 
     {"ip":"1.1.1.1","date":ISODate("2015-03-13T13:34:40.0Z")}, 
     {"ip":"2.2.2.2","date":ISODate("2015-03-13T13:34:40.0Z")}, 
     {"ip":"1.1.1.1","date":ISODate("2015-02-13T13:34:40.0Z")}, 
     {"ip":"1.1.1.1","date":ISODate("2015-02-13T13:34:40.0Z")} 
    ] 
}, 
{ 
    "id":2, 
    "url":"mysite2.com", 
    "views": 
    [ 
     {"ip":"1.1.1.1","date":ISODate("2015-01-13T13:34:40.0Z")}, 
     {"ip":"2.2.2.2","date":ISODate("2015-01-13T13:34:40.0Z")}, 
     {"ip":"1.1.1.1","date":ISODate("2015-02-13T13:34:40.0Z")}, 
     {"ip":"1.1.1.1","date":ISODate("2015-02-13T13:34:40.0Z")} 
    ] 
} 

Как я могу получить документы, где id = 1 и date(Y-m) = 2015-02?

ответ

0

Вы можете использовать aggregation pipeline operators. Ниже перечислены все вложенные документы в массиве views, которые соответствуют вашим критериям.

$match для фильтрации выбранного документа с данными id $unwind массив видов. На первом этапе $project используйте оператор $year, чтобы вернуть год на дату и $month месяц на дату. Затем отфильтруйте ваши документы по month и year, используя $match. $group ваш документ _id и используйте другой этап $project, чтобы изменить их.

db.collection.aggregate(
    [ 
     {'$match': {'id': 1}}, 
     {'$unwind': '$views'}, 
     {'$project': { 
      'id': 1, 
      'year': {'$year': '$views.date'}, 
      'month': {'$month': '$views.date'}, 
      'url': 1, 'views': 1 
      } 
     }, 
     {'$match': {'year': 2015, 'month': 2}}, 
     {'$group': { 
         '_id': '$id', 
         'url': {'$first': 'url'}, 
         'views': {'$push': '$views'} 
        } 
     }, 
     {'$project': {'id': '$_id', 'views': 1, 'url': 1, '_id': 0}} 
    ] 
) 

Результат

{ 
    "url" : "url", 
    "views" : [ 
      { 
        "ip" : "1.1.1.1", 
        "date" : ISODate("2015-02-13T13:34:40Z") 
      }, 
      { 
        "ip" : "1.1.1.1", 
        "date" : ISODate("2015-02-13T13:34:40Z") 
      } 
    ], 
    "id" : 1 
} 
0

Чтобы получить конкретный "views" элемент массива (целого документа), который удовлетворяет указанным выше критериям, использовать $elemMatch оператор проектирования следующим образом:

var start = new Date(2015, 0, 31, 23, 59, 59), 
    end = new Date(2015, 2, 1); 
db.test.find(
{ 
    id: 1, 
    "views.date": { "$gt": start, "$lt": end} 
}, 
{ 
    "id": 1, 
    "views": { 
     "$elemMatch": { 
      "date": { "$gt": start, "$lt": end} 
     } 
    } 
}); 

Возвращает:

/* 0 */ 
{ 
    "_id" : ObjectId("555089bf9cd8fa39c7971e33"), 
    "id" : 1, 
    "views" : [ 
     { 
      "ip" : "1.1.1.1", 
      "date" : ISODate("2015-02-13T13:34:40.000Z") 
     } 
    ] 
} 

Если вы хотите вернуть только весь документ затем использовать запрос диапазона дат без проекции $elemMatch следующим образом:

var start = new Date(2015, 0, 31, 23, 59, 59), 
    end = new Date(2015, 2, 1); 
db.test.find({id: 1, "views.date": { "$gt": start, "$lt": end}}) 

Приведенный выше запрос будет возвращать весь документ, согласованный указанным выше критериям, в том числе, как = ll вложенные документы:

/* 0 */ 
{ 
    "_id" : ObjectId("5550866d9cd8fa39c7971e2e"), 
    "id" : 1, 
    "url" : "mysite.com", 
    "views" : [ 
     { 
      "ip" : "1.1.1.1", 
      "date" : ISODate("2015-03-13T13:34:40.000Z") 
     }, 
     { 
      "ip" : "2.2.2.2", 
      "date" : ISODate("2015-03-13T13:34:40.000Z") 
     }, 
     { 
      "ip" : "1.1.1.1", 
      "date" : ISODate("2015-02-13T13:34:40.000Z") 
     }, 
     { 
      "ip" : "1.1.1.1", 
      "date" : ISODate("2015-02-13T13:34:40.000Z") 
     } 
    ] 
}