比方说,我有这样的收藏:
{
couponId: "abc",
state: "valid",
date: "2015-11-01"
}
{
couponId: "abc",
state: "expired",
date: "2015-10-01"
}
{
couponId: "abc",
state: "invalid",
date: "2015-09-01"
}
{
couponId: "xyz",
state: "invalid",
date: "2015-11-01"
}
{
couponId: "xyz",
state: "expired",
date: "2015-10-01"
}
{
couponId: "xyz",
state: "expired",
date: "2015-09-01"
}
...
优惠券可以有效/无效/过期。现在,我想获取一个优惠券列表,其中每个优惠券都是根据这个逻辑选择的:
将这一逻辑应用于上述列表应该会产生以下结果:
{
couponId: "abc", /* for "abc" "valid" exists */
state: "valid",
date: "2015-11-01"
},
{
couponId: "xyz", /* for "xyz" "valid" does not exist, use the next best "expired" */
state: "expired",
date: "2015-11-01"
}
基本上,有效>过期>无效
我曾经想过使用聚合操作,试图模仿SQL groupby+sort+selectFirst,
db.xyz.aggregate([
{$sort : { couponId: 1, state: -1 } },
{$group : { _id : "$couponId", document: {$first : "$$ROOT"} }}
])
显然,这是不起作用的,因为"state“字段应该有一个自定义排序( valid>expired>invalid )。因此,可以在聚合中实现自定义排序吗?
还是有更好的方法来做我在这里想做的事?
发布于 2015-10-29 20:02:17
一个更好的方法,尽管不是那么干净/漂亮(在我看来有点麻烦:P ),是在$cond管道阶段用上面的条件/逻辑嵌套一些$group操作符表达式。最好的解释是运行以下聚合管道:
db.xyz.aggregate([
{
"$group": {
"_id": "$couponId",
"state": {
"$first": {
"$cond": [
{ "$eq": ["$state", "valid"]},
"$state",
{
"$cond": [
{ "$eq": ["$state", "invalid"]},
"$state",
"expired"
]
}
]
}
},
"date": {
"$first": {
"$cond": [
{ "$eq": ["$state", "valid"]},
"$date",
{
"$cond": [
{ "$eq": ["$state", "invalid"]},
"$date",
{
"$cond": [
{ "$eq": ["$state", "expired"]},
"$date",
"1970-01-01"
]
}
]
}
]
}
}
}
}
])
样本输出
/* 0 */
{
"result" : [
{
"_id" : "xyz",
"state" : "invalid",
"date" : "2015-11-01"
},
{
"_id" : "abc",
"state" : "valid",
"date" : "2015-11-01"
}
],
"ok" : 1
}
https://stackoverflow.com/questions/33423161
复制相似问题