Reputation: 4352
I'd like to understand how this works:
I got collection with data like this:
{ _id: 5a854ee830093123a44bb7ec,
item: 124103,
owner: 'ZZZ',
quantity: 50, //between 1 and X (X is fixed and I determine it before, in this case it's 50)
lastModified: 1518685663000, //there are various lastModified intraday
price: 116000,
date: 2018-02-15 17:28:04.332 //default: new Date().toISOString()
}
and aggregation script:
x.aggregate([
{
$project: { year: { $year: "$date" },
month: { $month: "$date" },
day: { $dayOfMonth: "$date" },
item: "$item",
owner: "$owner",
quantity: "$quantity",
lastModified: "$lastModified",
price: "$price"}
},
{
$match: { item: 124103, day: 15, month: 2, year: 2018, lastModified: 1518685663000}
},
//and here I use my group stage
{
$group:
{
_id: "$item",
min_1: { $cond: { if: { $eq: [ "$quantity", 1] }, then: { $min: "$price" } } },
min_X: { $cond: { if: { $eq: [ "$quantity", X(50)] }, then: { $min: "$price" } } },
// then same for $max and $avg, (with different quantities) etc
},
},callback
What I want to receive:
in min_X
field I'd like to receive $min:$price
only if quantity
is equal to X value (50).
Actually I could receive necessary data via many queries, (which I actually do right now) but I guess people in StackOverflow community knows how to achieve the same result via 1 query with $match and $unwind.
Yes, I have already read the docs, but understood only that I should your $cond
operator. Guess someone could take me to the point up here, and provide relevant example. For example, in the future I'd like to operate with different $lastModified
intraday, it means, I'd like to $group data after $project
stage, then unwind cursor, and $group it with another $lastModified
.
Upvotes: 0
Views: 1997
Reputation: 37018
It's other way round $min
, then $cond
.
$group requires one of the accumulators for grouping fields. In your case it is $min
. Then you can apply a condition $cond
which value to use for aggregation. In case of $min
you can use Number.MAX_VALUE
for documents that don't match the criteria. It is always more or equal to any other value in javascript. You are free to use any sensible constant here.
After that you may want clean it up by replacing the junk numbers with nulls in another projection stage:
x.aggregate([
.....
{ $group: {
_id: "$item",
min_1: { $min: { $cond: [ { $eq: [ "$quantity", 1] }, "$price", Number.MAX_VALUE ] } },
min_50: { $min: { $cond: [ { $eq: [ "$quantity", 50] }, "$price", Number.MAX_VALUE ] } }
// then same for $max and $avg, (with different quantities) etc
} },
{ $project: {
min_1: { $cond: [ { $eq: [ "$min_1", Number.MAX_VALUE] }, null, "$min_1" ] },
min_50: { $cond: [ { $eq: [ "$min_50", Number.MAX_VALUE] }, null, "$min_50" ] }
} }
])
Upvotes: 1