【问题标题】:MongoDB aggregation with condition and unwind (one query instead of many)带有条件和展开的 MongoDB 聚合(一个查询而不是多个查询)
【发布时间】:2018-08-16 23:05:38
【问题描述】:

我想了解它是如何工作的:

我收集了这样的数据:

  { _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 字段中,我希望仅在 quantity 等于 X 值 (50) 时接收 $min:$price

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

是的,我已经阅读了文档,但只知道我应该使用您的 $cond 运算符。猜猜有人可以把我带到这里,并提供相关的例子。例如,将来我想在日内使用不同的$lastModified 进行操作,这意味着,我想在$project 阶段之后对数据进行$group,然后展开游标,并将其与另一个$lastModified 进行$group。

【问题讨论】:

  • 就目前而言,实际上问题出在$match 阶段,我可以指出我想要的所有内容,例如$match: {item: 124103, day: 15, month: 2, year: 2018, lastModified: 1518685663000, quantity: 200},然后在$group 阶段计算 min/max/avg /无论如何,问题是如何展开/更改 $match$match: {item: 124103, day: 15, month: 2, year: 2018, lastModified: 1518685663000, quantity: 1} 并将所有数据保存(或导出)在一个变量中
  • 就目前而言,问题是$project: { year: { $year: "$date" }, 导致提供的文档出错,因为那里没有date 字段。作为旁注,建议更新问题本身,而不是对其发表评论。
  • $project 完全没有问题,实际脚本运行良好。问题在于:如何在一个查询中(而不是多个)接收必要的数据
  • 您应该提供一个Complete, and Verifiable 示例。您提供的示例在项目阶段失败。
  • 哦是的,抱歉忘记复制粘贴它之前项目阶段,//修复

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


【解决方案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" ] }
    } }
])

【讨论】:

  • 顺便说一句,如果我理解正确的话,我可以随意使用$project 舞台,对吧?
  • 是的,实际上任何阶段。尽其所能。
猜你喜欢
  • 2021-01-11
  • 2017-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多