Вы в основном ищете оператора $cond
для того, чтобы оценить условия и возвращения, должен ли конкретный счетчик увеличивается на единицу или нет, но есть и некоторые другие понятия агрегации вы здесь отсутствуют:
db.trackings.aggregate([
{ "$match": {
"created_at": { "$gte": startDate, "$lt": endDate },
"country": "US",
"action": "like"
}},
{ "$group": {
"_id": {
"date": {
"month": { "$month": "$created_at" },
"day": { "$dayOfMonth": "$created_at" },
"year": { "$year": "$created_at" }
},
"article_id": "$article_id",
"state": "$state"
},
"male_like_count": {
"$sum": {
"$cond": [
{ "$eq": [ "$gender", "male" ] }
1,
0
]
}
},
"female_like_count": {
"$sum": {
"$cond": [
{ "$eq": [ "$gender", "female" ] }
1,
0
]
}
},
"unknown_like_count": {
"$sum": {
"$cond": [
{ "$eq": [ "$gender", "unknown" ] }
1,
0
]
}
}
}},
{ "$sort": {
"_id.date.year": 1,
"_id.date.month": 1,
"_id.date.day": 1,
"_id.article_id": 1,
"_id.state": 1,
"male_like_count": 1,
"female_like_count": 1
}}
]
)
Во-первых, вы в основном хотите $match
, вот как вы поставляете условия «запроса» для конвейера агрегации. В принципе это может быть любой этап конвейера, но при первом использовании он будет фильтровать вход, который рассматривается в следующих операциях. В этом случае требуемый диапазон дат, а также страна, и удаление чего-либо, что не является «похожим», поскольку вас не беспокоят эти цифры.
Затем все элементы сгруппированы по соответствующей клавише в _id
. Это может быть и используется как составное поле, главным образом потому, что все эти значения поля считаются частью ключа группировки, а также для небольшой организации.
Вы также, кажется, спрашиваете в своем выпуске для «отдельных полей» вне самого _id
. НЕ ДЕЛАЙТЕ ЭТО. Данные уже есть, поэтому нет смысла копировать его. Вы можете создавать одни и те же вещи за пределами _id
через $first
в качестве оператора агрегации, или вы даже можете использовать этап $project
в конце конвейера для переименования полей. Но это действительно лучше, если вы потеряете привычку, которая, по вашему мнению, вам нужна, поскольку она просто требует времени и пространства для получения ответа.
Если что-то еще, вы, кажется, после «красивой даты» больше всего на свете. Я лично предпочитаю работать с «датой математикой» для большинства манипуляций, и, следовательно, измененный список подходит для Mongoid будет:
Tracking.collection.aggregate([
{ "$match" => {
"created_at" => { "$gte" => startDate, "$lt" => endDate },
"country" => "US",
"action" => "like"
}},
{ "$group" => {
"_id" => {
"date" => {
"$add" => [
{ "$subtract" => [
{ "$subtract" => [ "$created_at", Time.at(0).utc.to_datetime ] },
{ "$mod" => [
{ "$subtract" => [ "$created_at", Time.at(0).utc.to_datetime ] },
1000 * 60 * 60 * 24
]}
]},
Time.at(0).utc.to_datetime
]
},
"article_id" => "$article_id",
"state" => "$state"
},
"male_like_count" => {
"$sum" => {
"$cond" => [
{ "$eq" => [ "$gender", "male" ] }
1,
0
]
}
},
"female_like_count" => {
"$sum" => {
"$cond" => [
{ "$eq" => [ "$gender", "female" ] }
1,
0
]
}
},
"unknown_like_count" => {
"$sum" => {
"$cond" => [
{ "$eq" =>[ "$gender", "unknown" ] }
1,
0
]
}
}
}},
{ "$sort" => {
"_id.date" => 1,
"_id.article_id" => 1,
"_id.state" => 1,
"male_like_count" => 1,
"female_like_count" => 1
}}
])
Который действительно просто сводится к получению DateTime
объекта подходит для использования в качестве аргумента драйвера, который соответствует к дате эпохи и выполнению различных операций. Если обработка $subtract
с одной датой BSON и другой будет выдавать числовое значение, которое затем может быть округлено до текущего дня с использованием прикладной математики. Тогда, конечно, при использовании $add
с цифровым значением временной метки до даты BSON (опять-таки представляющей эпоху) результат снова будет объектом BSON Date, с конечно скорректированным и округленным значением.
Тогда все дело в том, чтобы применить $sort
как этап конвейера агрегации снова, как это было предложено внешнему модификатору.Как и принцип $match
, конвейер агрегации может сортироваться в любом месте, но в конце всегда имеет дело с окончательным результатом.
Никогда не думал, что кто-то опубликует ответ так красиво. Большое спасибо @blakes Спасибо за то, что вы нашли решение для прекрасных дат. У меня есть два вопроса: (1) Какая польза от '_id.article_id' в параметрах сортировки? (2) Я считаю, что параметры сортировки работают в порядке сверху вниз, это означает, что сначала он будет сортировать по дате, а затем сортировать по состоянию, а затем male_like_count и женский, как count? правильно. Но если мне не нужен этот уровень сортировки, то передача только нужного ключа должна быть хорошей? – JVK