我在我的一个rails应用程序中使用Mongoid来获取mongodb
class Tracking
include Mongoid::Document
include Mongoid::Timestamps
field :article_id, type: String
field :action, type: String # like | comment
field :actor_gender, type: String # male | female | unknown
field :city, type: String
field :state, type: String
field :country, type: String
end
在这里,我想以这种表格形式获取记录,
article_id | state | male_like_count | female_like_count | unknown_gender_like_count | date
juhkwu2367 | California | 21 | 7 | 1 | 11-20-2015
juhkwu2367 | New York | 62 | 23 | 3 | 11-20-2015
juhkwu2367 | Vermont | 48 | 27 | 3 | 11-20-2015
juhkwu2367 | California | 21 | 7 | 1 | 11-21-2015
juhkwu2367 | New York | 62 | 23 | 3 | 11-21-2015
juhkwu2367 | Vermont | 48 | 27 | 3 | 11-21-2015
此处查询的输入为:
article_id
country
date range (from and to)
action (is `like` in this scenario)
sort_by [ date | state | male_like_count | female_like_count ]
这是我正在尝试的,通过在https://docs.mongodb.org/v3.0/reference/operator/aggregation/group/
引用一个例子db.trackings.aggregate(
[
{
$group : {
_id : { month: { $month: "$created_at" }, day: { $dayOfMonth: "$created_at" }, year: { $year: "$created_at" }, article_id: "$article_id", state: "$state", country: "$country"},
article_id: "$article_id",
country: ??,
state: "$state",
male_like_count: { $sum: ?? } },
female_like_count: { $sum: ?? } },
unknown_gender_like_count: { $sum: ?? } },
date: ??
}
}
]
)
那么我应该在??
的地方放置什么来比较按性别分列的数量以及如何为sorting_option
添加条款?
答案 0 :(得分:1)
您主要是在寻找$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
以外的“不同字段”。不要那样做。数据已经存在,因此复制它没有意义。您可以通过$first
作为聚合运算符在_id
之外生成相同的内容,或者您甚至可以在管道末尾使用$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日期和另一个BSON日期将产生一个数值,随后可以使用应用的数学舍入到当天。然后,当使用带有数字时间戳值的$add
到BSON日期(再次表示纪元)时,结果再次是BSON Date对象,当然还有调整后的舍入值。
然后,这只是将$sort
再次应用为聚合管道阶段,与外部修饰符相对应。与$match
原则非常相似,聚合管道可以在任何地方排序,但最后总是处理最终结果。