mongodb 为什么skip在聚合管道的开始不起作用,而在它的结尾起作用?

pinkon5k  于 2023-10-16  发布在  Go
关注(0)|答案(1)|浏览(129)

跳过阶段在此mongo数据库聚合框架管道的开头不起作用:

[
    {
      $skip: (!offset)?  0 :(offset-1)*limit
    },
    {
      $match: (query)? query : {}
    }
    ,
    {
      $lookup: ...,
    },
    {
      $lookup:..,
    },
    {
      $addFields: {
        userReact: {
          $arrayElemAt: [
            {
              $map: {
                input: {
                  $filter: {
                    input: '$reacts',
                    as: 'react',
                    cond: { $eq: ['$$react.publisher', viewerUserName || ''] },
                  },
                },
                as: 'react',
                in: '$$react.reactType',
              },
            },
            0,
          ],
        }
      },
    },
    {
      $project: {
        labels: 0,
        comments: 0,
        __v: 0,
        reacts: 0,
        publisher: 0,
      },
    },
    {
      $sort: {
        "publishDate": -1
      }
    },

    {
      $limit: limit
    }
  ]

但我这么说的话就行了

[
     <Same stages>
    {
      $skip: (!offset)?  0 :(offset-1)*limit
    },

    {
      $limit: limit
    }
  ]

我想知道什么样的手术会影响它以及最佳实践是什么。把跳跃台放在最上面比较好吗?

0pizxfdo

0pizxfdo1#

如果你正在尝试实现一种分页,你应该总是:

  1. $match根据您的参数过滤大多数文档
    1.执行$sort所需的任何操作(例如添加字段)
  2. $sort与您想要的字段(这里为publishDate)+_id字段({$sort: {"publishDate": -1, id : -1 } },)。_id部分对于保持结果的一致性很重要,因为2个文档对于publishDate可以具有相同的值,但对于_id不会具有相同的值
  3. $skip现在您的文档已排序
  4. $limit保持你想要的文档数量
    1.做额外的事情,如果你想在这里(投影等)
    如果你在排序前$skip,你会跳过随机的文档,这会破坏你的结果。
    我在mongoplayground上做了一个简单的例子。在这个例子中,我想让所有的“lemons”按键排序,跳过一个,保留其余的。
  • 如果我在$match之前先使用$skip,它将跳过第一个文档,这甚至不是一个柠檬-->错误选项
  • 如果我在$match之后但在$sort之前使用$skip,它将跳过一个lemon,但可能不是我想要的那个,因为它还没有排序--> WRONG OPTION(如果您更改集合中文档的顺序,它将更改输出)
  • 如果我在$sort之后使用$skip,我将始终得到相同的结果--> GOOD OPTION

相关问题