MongoDB 聚合 $group stage 通过已经创建的值/来自外部的变量

MongoDB aggregation $group stage by already created values / variable from outside

成像我有一个对象数组,在 aggregate 查询之前可用:

const groupBy = [
  {
    realm: 1,
    latest_timestamp: 1318874398, //Date.now() values, usually different to each other
    item_id: 1234, //always the same
  },
  {
    realm: 2,
    latest_timestamp: 1312467986, //actually it's $max timestamp field from the collection
    item_id: 1234,
  },
  {
    realm: ..., //there are many of them
    latest_timestamp: ...,
    item_id: 1234,
  },
  {
    realm: 10,
    latest_timestamp: 1318874398, //but sometimes then can be the same
    item_id: 1234,
  },
]

和具有以下架构的集合 (example set available on MongoPlayground):

  {
    realm: Number,
    timestamp: Number,
    item_id: Number,
    field: Number, //any other useless fields in this case
  }

我的问题是,如何使用已经可用的数据集(来自 groupBy)通过聚合框架 $group 从集合中获取值?

已经尝试过了。

好的,让我们跳过废话,比如:

for (const element of groupBy) {
  //array of `find` queries
}

我当前的工作聚合查询是这样的:

      //first stage
      {
         $match: { 
           "item": 1234
           "realm" [1,2,3,4...,10]
         }
      },
      {
        $group: {
          _id: {
            realm: '$realm',
          },
          latest_timestamp: {
            $max: '$timestamp',
          },
          data: {
            $push: '$$ROOT',
          },
        },
      },
      {
        $unwind: '$data',
      },
      {
        $addFields: {
          'data.latest_timestamp': {
            $cond: {
              if: {
                $eq: ['$data.timestamp', '$latest_timestamp'],
              },
              then: '$latest_timestamp',
              else: '$$REMOVE',
            },
          },
        },
      },
      {
        $replaceRoot: {
          newRoot: '$data',
        },
      },
      //At last, after this stages I can do useful job

但我发现它有点过时,而且我已经听说使用 [.mapReduce][1] 可以比此查询更快地解决我的问题。 (但官方文档对此并不乐观)是真的吗?

至于现在,在开始处理有用的(对我而言)文档之前,我使用了 4 或 5 个阶段。

最近更新:

我检查了 $facet 阶段,我发现它对这种情况很好奇。可能它会帮助我。

物有所值:

在经过必要的阶段后收到文件后,我正在构建一个具有代表性的聚类图,您可能也知道 as a heatmap

之后,我逐一迭代每个文档(或对象数组)以找到它们正确的 xy协调到位应该是:

[
  { 
    x: x (number, actual $price), 
    y: y (number, actual $realm),
    value: price * quantity,
    quantity: sum_of_quantity_on_price_level
  }
]

至于现在,它是旧的糟糕代码,for...循环在彼此内部,但在未来,我将使用 $facet => $bucket 运算符来完成这种工作.

所以,我用另一种相关的方式找到了我的问题的答案。

我正在考虑使用 $facet 运算符,老实说,它仍然是一个选项,但是使用它,如下所示是一个不好的做法。

//building $facet query before aggregation

const ObjectQuery = {}
for (const realm of realms) {
  Object.assign(ObjectQuery, { `${realm.name}` : [ ... ] }
}

//mongoose query here
aggregation([{
    $facet: ObjectQuery
  },
  ...
])

因此,我选择了 $project 阶段和 $switch 运算符来过滤结果,例如 $groups 做的。

此外,使用MapReduce也可以解决这个问题,但由于某些原因,官方Mongo文档recommends to avoid using it,并选择聚合:$group和$merge运算符。