如何对 MongoDB 聚合管道使用多个运算符?

How to use multiple operators to a MongoDB aggregation pipeline?

我有一个包含此架构中的文档的集合(是的,我知道这是 无架构的世界 ):

{
  name: "Real Colicos",
  fee: 123,
  creator: {},
  participants: [{},{}]
}

所以,我需要一个 查询,我可以在其中获得按参与者计数 排序的第一个组。当然,我可以有一个 participantsCount 属性并在更新时使用 $inc 增加它,但我觉得这是一种幼稚的方法。这是聚合还是 map reduce 领域?

编辑。解决方案是使用 aggregate:

来自 docs 我可以接受这个:

  db.groups.aggregate(
    [
      {
        $project: {
          name: 1,
          participantsCount: {$size: "$participants"}
        }
      }
    ])

这有效。现在我想知道,如何对搜索进行分页,按 participantsCount 排序并仅包含一些文档属性?

我试过:

  db.groups.aggregate(
    [
      {

        $project: {
          name: 1,
          participantsCount: {$size: "$participants"}
        },
        $skip: 10,
        $limit: 5,
        $sort: {participantsCount: -1},
        $match: {isPrivate: false}

      }
    ],
    function (err, results) {
      console.log(results);
    }
  );

但抛出 undefined 作为结果。

还有:

  db.groups.aggregate(
    [
      {

        $project: {
          name: 1,
          participantsCount: {$size: "$participants"}
        },
        {$skip: 10},
        {$limit: 5},
        {$sort: {participantsCount: -1}},
        {$match: {isPrivate: false}}

      }
    ],
    function (err, results) {
      console.log(results);
    }
  );

抛出一个空数组。

甚至:

db.groups.aggregate(
    [
      {$project: {name: 1, isPrivate: 1, participantsCount: {$size: "$participants"}}},
      {$match: {isPrivate: false}},
      {$skip: 10},
      {$limit: 5},
      {$sort: {participantsCount: -1}}
    ],
    function (err, results) {
      console.log(results);
    }
  );

这也会抛出一个空数组。

我可以看到两个紧迫的问题:

  1. 阶段未正确流水线化。它们目前都是一个对象的一部分,但应该作为单独的文档出现在数组中:
    db.groups.aggregate(
        [
          {$project: {name: 1, participantsCount: {$size: "$participants"}}},
          {$skip: 10},
          {$limit: 5},
          {$sort: {participantsCount: -1}},
          {$match: {isPrivate: false}}
        ],
        function (err, results) {
          console.log(results);
        }
      );
  1. 没有任何内容会通过最后一个 $match,因为 isPrivate 在第一个 $project 中被剥离。您可能需要在 $project.
  2. 中包含该字段

答案:聚合可以是管道。

来自文档:

The aggregation pipeline is a framework for data aggregation modeled on the concept of data processing pipelines. Documents enter a multi-stage pipeline that transforms the documents into an aggregated results.

If your aggregation operation requires only a subset of the data in a collection, use the $match, $limit, and $skip stages to restrict the documents that enter at the beginning of the pipeline.

所以这意味着处理管道以获得想要的结果。正如第二段所暗示的,管道处理顺序很重要

它应该是这样的:

collection.aggregate(
    [
      {$match: {isPrivate: false}},
      {$skip: 0},
      {$limit: 2},
      {$project: {name: 1, participantsCount: {$size: "$participants"}}},
      {$sort: {participantsCount: -1}}
    ]
  );