对现有的Mongoose聚合结果执行其他聚合

时间:2021-01-19 02:54:00

I want to take the result of a Mongoose Model.aggregate command and perform additional aggregation methods on it. The idea is that I can query the database just once, aggregate to a certain point, then perform additional aggregation methods on those results without having to requery the database again. (Code below is Coffeescript)

我想获取Mongoose Model.aggregate命令的结果并对其执行其他聚合方法。我的想法是,我可以只查询一次数据库,聚合到某个点,然后对这些结果执行其他聚合方法,而无需再次重新查询数据库。 (以下代码为Coffeescript)

firstAggregation = [
    {
      $geoNear: {
        near:
          type: "Point"
          coordinates: geo
        includeLocs: "geo"
        distanceField: "distance"
        maxDistance: distance
        spherical: true
        uniqueDocs: true
      }
    },
    {
      $match: { "active" : true }
    }
  ]

secondAggregation = firstAggregation.concat [
        {
          $unwind: "$offers"
        },
        {
          $group: {
            _id: "$offers"
          }
        }
      ]

app.MyModel.aggregate firstAggregation, (err, results) ->

  # ... do something with the first results ...

  # **** apply secondAggregation here! ****
  # the below doesn't work, but its what I want to achieve

  results.aggregate secondAggregation, (err, secondResults) ->
    # ... do something with the second results without having requeried the DB ...

Is this possible?

这可能吗?

1 个解决方案

#1


1  

No, you can't pass in the results from one aggregation to a second aggregation. While you could pass a list of document _ids to filter on using $in, beyond that, there's really not much else you could do.

不,您无法将结果从一个聚合传递到第二个聚合。虽然您可以传递一个文档_ids列表来使用$ in进行过滤,但除此之外,您可以做的其他事情并不多。

{ $match : { _id : { $in: [ /* list of _ids */] } } } 

Although given current v2.4 limitations of the aggregation framework results (capped at a 16MB result), you could perform similar logic to what you might want to have done on the database in memory on the client (in this case NodeJS).

虽然给定了聚合框架结果的当前v2.4限制(上限为16MB),但您可以执行类似于客户端(在本例中为NodeJS)的内存中数据库的逻辑。

In the example above in your question, it looks like it's just for example trying to find all of the distinct values for an array of values for the field offers?

在您的问题上面的示例中,它看起来只是例如尝试查找字段提供的值数组的所有不同值?

offerNames = {}
for result in results
    for offer in result.offers
        offerNames[i] = (offerNames[i] or 0) + 1

for name, value of offerNames
    console.log name + " = " + value

#1


1  

No, you can't pass in the results from one aggregation to a second aggregation. While you could pass a list of document _ids to filter on using $in, beyond that, there's really not much else you could do.

不,您无法将结果从一个聚合传递到第二个聚合。虽然您可以传递一个文档_ids列表来使用$ in进行过滤,但除此之外,您可以做的其他事情并不多。

{ $match : { _id : { $in: [ /* list of _ids */] } } } 

Although given current v2.4 limitations of the aggregation framework results (capped at a 16MB result), you could perform similar logic to what you might want to have done on the database in memory on the client (in this case NodeJS).

虽然给定了聚合框架结果的当前v2.4限制(上限为16MB),但您可以执行类似于客户端(在本例中为NodeJS)的内存中数据库的逻辑。

In the example above in your question, it looks like it's just for example trying to find all of the distinct values for an array of values for the field offers?

在您的问题上面的示例中,它看起来只是例如尝试查找字段提供的值数组的所有不同值?

offerNames = {}
for result in results
    for offer in result.offers
        offerNames[i] = (offerNames[i] or 0) + 1

for name, value of offerNames
    console.log name + " = " + value