2014-11-22 3 views
0

У меня есть документ, который включает в себя поле, как это:MongoDB: Как подсчитать поле, если оно соответствует условию?

{ 
... 
log: [ 
    { 
     utc_timestamp: ISODate("2014-11-15T10:26:47.337Z"), 
     type: "clicked" 
    }, 
    { 
     utc_timestamp: ISODate("2014-10-15T16:12:51.959Z"), 
     type: "emailed" 
    }, 
    { 
     utc_timestamp: ISODate("2014-10-15T16:10:51.959Z"), 
     type: "clicked" 
    }, 
    { 
     utc_timestamp: ISODate("2014-09-15T04:59:19.431Z"), 
     type: "emailed" 
    }, 
    { 
     utc_timestamp: ISODate("2014-09-15T04:58:19.431Z"), 
     type: "clicked" 
    }, 
    ], 
    ... 
} 

Как получить количество записей журнала типа «щелкнул» с этого месяца, если только не существует регистрационная запись типа «по электронной почте " этот месяц?

Другими словами, я хочу узнать, какие клики не были отправлены связанное электронное письмо.

Таким образом, в этом примере счет будет равен 1, так как в последней записи с щелчком отсутствует запись «по электронной почте».

Примечание: для этого прецедента клики не имеют уникальных идентификаторов - это все данные, которые регистрируются.

+0

Если я правильно понял, что журнал является собственностью документа, я думаю, что решение будет включать в себя $ unwind. Кроме того, я думаю, что отдельные клики должны иметь уникальные значения _id, даже если вы их не ожидали. Свойство _id автоматически добавляется к членам массива поддокумента, хотя, возможно, вы его подавили? – Semicolon

+0

@Semicolon Я не знал о том, что свойство _id автоматически назначается для членов массива поддокумента. Кажется, MongoEngine действительно подавляет это - журнал настроен как «ListField», и я просто добавляю словарь к нему. – okoboko

ответ

0

Используйте следующую агрегацию трубопровода:

db.click_log.aggregate([ 
    { "$match" : { "log.type" : { "$ne" : "emailed" } } }, // get rid of docs with an "emailed" value in log.type and docs not from this month 
    { "$unwind" : "$log" }, // unwind to get log elements as separate docs 
    { "$project" : { "_id" : 1, "log" : 1, "month" : { "$month" : "$log.utc_timestamp" } } }, 
    { "$match" : { "log" : "clicked", "month" : <# of month> } }, // get rid of log elements not from this month and that aren't type clicked 
    { "$group" : { "_id" : "$_id", "count" : { "$sum" : 1 } } } // collect clicked elements from same original doc and count number 
]) 

Это будет возвращать, для каждого документа, не имея «по электронной почте» в качестве значения log.type , количество элементов массива log, которые имеют log.type значение clicked и с меткой времени с текущего месяца. Если вы хотите скользящий 30-дневный период в течение месяца, измените $match на запрос диапазона с $gt и $lt, охватывающий необходимый период времени.

0

Вы можете использовать запрос, похожий на ниже.

db.dbversitydotcom_col.aggregate([ { $unwind: “$log” }, 
    { $match: { “log.type” : “clicked”, "log.utc_timestamp" : "your required date" } }, 
    { $sort: { “Files.Size” : -1.0 } }, { $limit: 5.0 } ]).count() 

Пожалуйста, обратитесь к http://dbversity.com/mongodb-importance-of-aggregation-framework/ для более подробного объяснения,

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