2014-04-27 3 views
0

Я новичок в MongoDB, и я пытаюсь выяснить, как считать все возвращенный запрос внутри массива документов, как показано ниже:запрос Количество дополнительных коллекций MongoDB

"impression_details" : [ 
     { 
      "date" : ISODate("2014-04-24T16:35:46.051Z"), 
      "ip" : "::1" 
     }, 
     { 
      "date" : ISODate("2014-04-24T16:35:53.396Z"), 
      "ip" : "::1" 
     }, 
     { 
      "date" : ISODate("2014-04-25T16:22:20.314Z"), 
      "ip" : "::1" 
     } 
] 

Что я хотел бы do подсчитывает, сколько 2014-04-24 есть (что равно 2). На данный момент мой запрос такой, и он не работает:

db.banners.find({ 
    "impression_details.date":{ 
     "$gte": ISODate("2014-04-24T00:00:00.000Z"), 
     "$lte": ISODate("2014-04-24T23:59:59.000Z") 
    } 
}).count() 

Не уверен, что происходит, пожалуйста, помогите!

спасибо.

ответ

0

Концепция здесь является то, что существует четкое различие между выбором документов и выбором элементов массива поддокумента. Так что происходит в настоящее время в вашем запросе именно то, что должно происходить. Поскольку документ содержит хотя бы одну запись субдокумента, которая соответствует вашему условию, то этот документ будет найден.

Чтобы «фильтровать» содержимое самих субдокументов для нескольких совпадений, вам необходимо применить метод .aggregate(). А так как вы ожидаете подсчет, то это то, что вы хотите:

db.banners.aggregate([ 

    // Matching documents still makes sense 
    { "$match": { 
     "impression_details.date":{ 
      "$gte": ISODate("2014-04-24T00:00:00.000Z"), 
      "$lte": ISODate("2014-04-24T23:59:59.000Z") 
     } 
    }}, 

    // Unwind the array 
    { "$unwind": "$impression_details" }, 

    // Actuall filter the array contents 
    { "$match": { 
     "impression_details.date":{ 
      "$gte": ISODate("2014-04-24T00:00:00.000Z"), 
      "$lte": ISODate("2014-04-24T23:59:59.000Z") 
     } 
    }}, 

    // Group back to the normal document form and get a count 
    { "$group": { 
     "_id": "$_id", 
     "impression_details": { "$push": "$impression_details" }, 
     "count": { "$sum": 1 } 
    }} 

]) 

И это даст вам форму, которая имеет только те элементы, которые соответствуют запросу в массиве, а также обеспечивая количество этих записей которые были сопоставлены.

+0

Wow thanks, я думаю, что понимаю ваш ответ, прочитаю больше о документах mongodb. – jonprasetyo

0

Использование оператора $elemMatch сделает все, что вы пожелаете.
В вашем запросе измерять все документы, чье поле impression_details содержит данные между ISODate («2014-04-24T00: 00: 00.000Z») и ISODate («2014-04-24T23: 59: 59.000Z») , Дело в том, что он вернет весь документ, который вам не нужен. Так что, если вы хотите только поддокументы, который удовлетворяет ваше состояние:

var docs = db.banners.find({ 
    "impression_details": { 
     $elemMatch: { 
      data: { 
       $gte: ISODate("2014-04-24T00:00:00.000Z"), 
       $lte: ISODate("2014-04-24T23:59:59.000Z") 
      } 
     } 
    } 
}); 
var count = 0; 
docs.forEach(function(doc) { 
    count += doc.impression_details.length; 
}); 
print(count); 
+0

Обратите внимание на название вопроса и что OP ожидает совпадения с количеством записей в массиве вспомогательных документов –

+0

@NeilLunn. Вы правы. Я редактирую свой ответ. – yaoxing

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