MongoDB数组分页-检查$slice是否到达数组的开头

MongoDB数组分页-检查$slice是否到达数组的开头,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,在我的应用程序中,我有一个用户可以阅读评论的框。如果某个用户向下滚动,它会加载越来越多的评论,一切正常。我从头到尾分割数组,因为每当有人写评论时,我都使用$push,所以我像这样分割它$slice:[-5,5]。这将从数组中分割最后5个元素。-5实际上是我的聚合管道中的一个变量。每当我加载一些注释时,我都会将值从-5减小到-10,依此类推。我在这里遇到的问题是,如果我的数组的长度为50,那么我执行这个slice$slice:[-70,5]我会得到前5条注释,但我希望得到0。结果是,我有一个无限滚

在我的应用程序中,我有一个用户可以阅读评论的框。如果某个用户向下滚动,它会加载越来越多的评论,一切正常。我从头到尾分割数组,因为每当有人写评论时,我都使用
$push
,所以我像这样分割它
$slice:[-5,5]
。这将从数组中分割最后5个元素。
-5
实际上是我的聚合管道中的一个变量。每当我加载一些注释时,我都会将值从
-5
减小到
-10
,依此类推。我在这里遇到的问题是,如果我的数组的长度为50,那么我执行这个slice
$slice:[-70,5]
我会得到前5条注释,但我希望得到0。结果是,我有一个无限滚动条,它在相同的5条第一条评论上反复加载。我该如何解决这个问题

let result = await Post.aggregate([
    {
      $match: {
        _id: userId,
        "posts._id": postId
      }
    },
    {
      $addFields: {
        posts: {
          $map: {
            input: "$posts",
            as: "p",
            in: {
              _id: "$$p._id",
              comments: { $slice: ["$$p.comments", -start, 5] }
            }
          }
        }
      }
    },
    {
      $project: {
        posts: {
          $filter: {
            input: "$posts",
            as: "posts",
            cond: { $eq: ["$$posts._id", postId] }
          }
        }
      }
    }
  ]);

一种方法是使用
$cond
运算符:

查询:

let inputPosition = -70
let positionConverted = -position // 70
let maxNumber = 1000

db.collection.aggregate([
    {
      $project: {
        comments: {
          $slice: [ "$comments",
            { $cond: [ { $gte: [ { $size: "$comments" }, positionConverted ] }, inputPosition, maxNumber ] }, 5 ] }
      }
    }
  ])
测试:

说明:

let inputPosition = -70
let positionConverted = -position // 70
let maxNumber = 1000

db.collection.aggregate([
    {
      $project: {
        comments: {
          $slice: [ "$comments",
            { $cond: [ { $gte: [ { $size: "$comments" }, positionConverted ] }, inputPosition, maxNumber ] }, 5 ] }
      }
    }
  ])

所以
$slice
的语法是
{$slice:[

一种方法是使用
$cond
运算符:

查询:

let inputPosition = -70
let positionConverted = -position // 70
let maxNumber = 1000

db.collection.aggregate([
    {
      $project: {
        comments: {
          $slice: [ "$comments",
            { $cond: [ { $gte: [ { $size: "$comments" }, positionConverted ] }, inputPosition, maxNumber ] }, 5 ] }
      }
    }
  ])
测试:

说明:

let inputPosition = -70
let positionConverted = -position // 70
let maxNumber = 1000

db.collection.aggregate([
    {
      $project: {
        comments: {
          $slice: [ "$comments",
            { $cond: [ { $gte: [ { $size: "$comments" }, positionConverted ] }, inputPosition, maxNumber ] }, 5 ] }
      }
    }
  ])

因此,
$slice
的语法是
{$slice:[

@lfaruki,我认为你在正确的轨道上反转数组,正如@whoami所解释的那样

如果为正,
$slice
确定从数组开始的起始位置。如果
大于元素数,则
$slice
返回空数组


我不确定您在尝试使用反向数组实现它时遇到了什么问题。但我的一般建议是,这会对大型数组的性能产生负面影响。如果您的注释已经存在于单独的集合中,最好使用“基于时间的”“基于光标的”单独查询分页。因为MongoDB最终对文档大小有限制,并且您不想在聚合中处理大型数组。

@lfaruki,我认为您正在正确的轨道上反转数组,正如@whoami所解释的那样

如果为正,
$slice
确定从数组开始的起始位置。如果
大于元素数,则
$slice
返回空数组


我不确定您在尝试使用反向数组实现它时遇到了什么问题。但我的一般建议是,这会对大型数组的性能产生负面影响。如果您的注释已经存在于单独的集合中,最好使用“基于时间的”“基于光标的”单独查询分页。因为MongoDB最终对文档大小有限制,并且您不想在聚合中处理大型数组。

效果很好。但是您只需要将
$gt
更改为
$gte
就可以了,我有21个元素,所以当我的输入为25时,它不会执行查询,这意味着1个元素不会被删除isplayed@Ifaruki:您的数组有多大?尝试反转数组,然后进行分页如何?每次反转都可能是一种过度杀伤力,但又如何?或者,您可以通过反转现有数组来更新所有文档&在新写入之后,使用将新注释推送到
注释
数组的
0
位置
$position
operator.its现在是0,我不知道将来会有多大。我已经做了一个查询,在那里我反转数组并分页。这次我尝试像这样切片,但似乎更难,然后我认为也可以优化此查询,对我来说,它看起来太大了,无法在嵌套的arrayworks gr中切片5项但是有一件事你需要把
$gt
改成
$gte
,我有21个元素,所以当我的输入是25时,它不会执行查询,这意味着1个元素不会被删除displayed@Ifaruki:您的阵列可以有多大?尝试反转阵列然后进行分页如何?每次反转都可能是一种过度杀伤力但是那又如何呢?或者一旦你可以通过反转现有的数组来更新所有文档&在新的写入之后,使用
$position
操作符将新的注释推送到
comments
数组的
位置。现在是0,我不知道将来会有多大。我做了一个查询,在那里我反转数组并通过gh.这次我试着像这样切片,但似乎更难,然后我认为也可以优化这个查询,对我来说,它看起来太大了,无法在嵌套数组中切片5个项目只是一个观察;如果使用数组索引来获取元素,如果新项目在计数时到达。它不都移到后面,你会d获取重复的项目?是否最好使用基于时间的值,如
ObjectId
?只是观察;如果使用数组索引获取元素,如果新项目在计数时到达。是否所有项目都移到后面,您将获得重复的项目?是否最好使用基于时间的值,如
ObjectId
inste公元