【问题标题】:MongoDB - Pagination based on non-unique fieldsMongoDB - 基于非唯一字段的分页
【发布时间】:2012-12-24 12:07:02
【问题描述】:

我熟悉 range based pagination 在大型 MongoDB 集合上的最佳实践,但是我正在努力弄清楚如何对排序值位于非唯一字段上的集合进行分页。

例如,我有大量用户,有一个字段表示他们做某事的次数。该字段绝对是非唯一的,并且可能有大量具有相同值的文档。

我想返回按“numTimesDoneSomething”字段排序的结果。

这是一个示例数据集:

{_id: ObjectId("50c480d81ff137e805000003"), numTimesDoneSomething: 12}
{_id: ObjectId("50c480d81ff137e805000005"), numTimesDoneSomething: 9}
{_id: ObjectId("50c480d81ff137e805000006"), numTimesDoneSomething: 7}
{_id: ObjectId("50c480d81ff137e805000007"), numTimesDoneSomething: 1}
{_id: ObjectId("50c480d81ff137e805000002"), numTimesDoneSomething: 15}
{_id: ObjectId("50c480d81ff137e805000008"), numTimesDoneSomething: 1}
{_id: ObjectId("50c480d81ff137e805000009"), numTimesDoneSomething: 1}
{_id: ObjectId("50c480d81ff137e805000004"), numTimesDoneSomething: 12}
{_id: ObjectId("50c480d81ff137e805000010"), numTimesDoneSomething: 1}
{_id: ObjectId("50c480d81ff137e805000011"), numTimesDoneSomething: 1}

如何返回这个按“numTimesDoneSomething”排序的数据集,每页有 2 条记录?

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    在这种情况下,您可以对多个字段进行排序,对numTimesDoneSomethingid 字段进行排序。由于 id_ 字段本身已经根据插入时间戳在升序,因此您将能够在集合中分页而无需迭代重复数据,除非在迭代期间插入新数据。

    db.collection.find().sort({numTimesDoneSomething:-1, _id:1}).offset(index).limit(2)
    

    【讨论】:

      【解决方案2】:

      @cubbuk 展示了一个使用 offset (skip) 的好例子,但您也可以将他显示的查询建模为范围分页:

      db.collection.find().sort({numTimesDoneSomething:-1, _id:1})
      

      由于这里的_id 是唯一的,并且您正在支持它,您实际上可以按_id 进行范围,结果,即使在具有numTimesDoneSomething12 的两条记录之间,关于是否它们应该位于一页或下一页。

      所以做一些像

      这样简单的事情
      var q = db.collection.find({_id: {$gt: last_id}}).sort({numTimesDoneSomething:-1, _id:1}).limit(2)
      

      应该非常适合远程分页。

      【讨论】:

      • find({_id: last_id}) 不会只返回一条记录吗?
      • 查找查询需要大于 last_id 不是吗?您的解决方案还涵盖了新插入 +1 的情况 =)
      • @AdamDuro 不错的地方 :) 现在修复了
      • 很抱歉删除这个答案,但这不可能。 _id 上的二级排序并不排除具有 older id 的文档在分页中 later 出现。如果您只是查询 $gt 最后一个 id,您将丢弃所有可能具有较少 numTimes 的旧文档。为此,我相信您需要查询$or: [{numtimes: last_numTimes, _id: last_id}, {numTimes: {$lt: last_numTimes}},请原谅代码释义。如果我错了,请批评我。我自己目前正在努力解决非唯一范围分页的问题,正在寻找答案。
      • @Sammaye 对,但 _id 只是次要排序,只有在 numX相同时才会影响顺序。结果很可能看起来像{numX: 2, _id: 2}, {numX: 2, _id: 3}, {numX: 1, _id: 1}。在这种情况下,如果您的页面在第二个文档上结束,将导致_id > 3 的“下一页”查询,这将抛出第三个结果。在真正的查询中,你会抛出更多。
      猜你喜欢
      • 1970-01-01
      • 2016-06-22
      • 2014-04-04
      • 1970-01-01
      • 2010-11-13
      • 2013-10-08
      • 2011-10-11
      • 2012-05-10
      相关资源
      最近更新 更多