Let's say I have a collection like:
{
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"
}
...
a coupon can be valid/invalid/expired. Now, I want to fetch a list of coupons, where each coupon is selected based on this logic:
- if a "valid" coupon exists, use that
- else if an "expired" coupon exists, use that
- else get the "invalid" coupon.
applying this logic to the above list should yield:
{
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"
}
basically, valid > expired > invalid
I have thought of using an aggregate operation, trying to emulate a SQL groupby+sort+selectFirst,
db.xyz.aggregate([
{$sort : { couponId: 1, state: -1 } },
{$group : { _id : "$couponId", document: {$first : "$$ROOT"} }}
])
And obviously this doesn't work, because the "state" field should have a custom sorting where valid>expired>invalid. So, can custom sorting be achieved in an aggregation?
Or is there a better way of doing what I'm trying to do here?