带条件和展开的MongoDB聚合(一个查询而不是多个)

时间:2018-03-08 14:39:55

标签: node.js mongodb mongoose aggregation-framework aggregate

我想了解这是如何运作的:

我收集了这样的数据:

  { _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()
  }

和聚合脚本:

    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

我想收到什么:

min_X字段中

我希望仅在$min:$price等于X值(50)时才会收到quantity

实际上我可以通过许多查询接收必要的数据(我实际上现在正在做)但我猜StackOverflow社区的人们知道如何通过$ match和$ unwind的1个查询来实现相同的结果。

是的,我已经阅读了文档,但只了解我应该是$cond运营商。猜猜有人可以带我到这里,并提供相关的例子。例如,将来我希望在不同的$lastModified日内操作,这意味着,我希望在$project阶段之后对数据进行分组,然后展开光标和$将其与另一个$lastModified分组。

1 个答案:

答案 0 :(得分:1)

它是$min的另一种方式,然后是$cond

$group需要其中一个accumulators用于分组字段。在您的情况下,它是$min。然后,您可以应用条件$cond哪个值用于聚合。如果是$min,您可以将Number.MAX_VALUE用于与条件不符的文档。它总是大于或等于javascript中的任何其他值。你可以在这里自由使用任何明智的常数。

之后你可能想要通过在另一个投影阶段用空值替换垃圾数来清理它:

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" ] }
    } }
])