【问题标题】:How to get the last N records in mongodb?如何获取mongodb中的最后N条记录?
【发布时间】:2011-05-24 04:49:24
【问题描述】:

我在任何地方都找不到它的记录。默认情况下,find() 操作将从头开始获取记录。如何获取mongodb的最后N条记录?

编辑:我也希望返回的结果从最近到最近,而不是相反。

【问题讨论】:

  • @Haim,请具体回答,网页的哪个部分解决了我的问题?
  • 嗨@BinChen,我最近也遇到同样的问题,请问解决了吗?

标签: mongodb record


【解决方案1】:

查看查询:排序和自然顺序,http://www.mongodb.org/display/DOCS/Sorting+and+Natural+Order 以及 Cursor Methods 下的 sort() http://www.mongodb.org/display/DOCS/Advanced+Queries

【讨论】:

  • 感谢您的回答,它已接近,但我想返回从最近到最近排序的记录,可以吗?
  • 不应依赖自然秩序;如果您使用的是副本集(并且应该如此),不同的节点很可能会将相同的文档以不同的顺序存储在磁盘上。
  • 如果要获取最新记录,则必须依赖文档中的日期字段。
【解决方案2】:

如果我理解你的问题,你需要按升序排序。

假设您有一些名为“x”的 id 或日期字段,您会这样做......

.sort()


db.foo.find().sort({x:1});

1 将按升序排序(从旧到新),-1 将按降序排序(从新到旧)。

如果您使用自动创建的 _id 字段,它会嵌入一个日期...因此您可以使用它来订购...

db.foo.find().sort({_id:1});

这将返回您的所有文档,从最旧到最新排序。

自然秩序


你也可以使用上面提到的Natural Order...

db.foo.find().sort({$natural:1});

同样,根据您想要的顺序使用 1-1

使用 .limit()


最后,在进行这种广泛开放的查询时添加限制是一种很好的做法,这样您就可以做到...

db.foo.find().sort({_id:1}).limit(50);

db.foo.find().sort({$natural:1}).limit(50);

【讨论】:

  • @MortezaM。我很确定您的查询顺序混淆了...您的 sort() 应该最后运行,而不是首先运行(很像 SQL ORDER BY).find({}).skip(1) .limit(50).sort({"date":-1})
  • 无论如何,调用函数的顺序应该与最终结果无关。
  • @MortezaM。当然顺序很重要。 item = 3; item.add(3).divide(3) == 2; item.divide(3).add(3) == 4; 没有顺序会是什么结果???我同意你的观点,这种颠倒的顺序并不直观。毕竟这不是 SQL,它应该遵循正常的 OO 范例。
  • 但顺序并不重要。您所要做的就是尝试它,看看它没有。所有这些都在游标上调用并传递给服务器,因此服务器限制排序结果(前 N 个),因为其他任何东西都没有意义。
  • 文档确认订单无关紧要:link
【解决方案3】:

你可以使用sort()limit()skip()从任何跳过的值开始获取最后N条记录

db.collections.find().sort(key:value).limit(int value).skip(some int value);

【讨论】:

    【解决方案4】:

    可以使用以下查询查看最近添加的 N 个记录,从最近到最近:

    db.collection.find().skip(db.collection.count() - N)
    

    如果您希望它们以相反的顺序排列:

    db.collection.find().sort({ $natural: -1 }).limit(N)
    

    如果你安装Mongo-Hacker你也可以使用:

    db.collection.find().reverse().limit(N)
    

    如果您厌倦了一直编写这些命令,您可以在 ~/.mongorc.js 中创建自定义函数。例如

    function last(N) {
        return db.collection.find().skip(db.collection.count() - N);
    }
    

    然后在 mongo shell 中输入 last(N)

    【讨论】:

    • db.collection.find().reverse().limit(1) 给了我错误... has no method reverse
    • @Catfish 你是对的,我刚刚注意到 reverse() 是由 [Mongo-Hacker ](tylerbrock.github.com/mongo-hacker) 添加的,我会更新我的答案。谢谢。
    • db.getCollection('COLLECTION_NAME').find().skip(db.getCollection('COLLECTION_NAME').count()-N) 非常适合我 :)
    • 这应该是问题的答案,而不是 Justin Jenkins 的答案。
    • 不应依赖自然秩序;如果您使用的是副本集(并且应该如此),不同的节点很可能会将相同的文档以不同的顺序存储在磁盘上。
    【解决方案5】:

    为了获取最后 N 条记录,您可以执行以下查询:

    db.yourcollectionname.find({$query: {}, $orderby: {$natural : -1}}).limit(yournumber)
    

    如果您只想要最后一条记录:

    db.yourcollectionname.findOne({$query: {}, $orderby: {$natural : -1}})
    

    注意:代替$natural,您可以使用您的收藏中的一列。

    【讨论】:

    • 这对我有用 db.yourcollectionname.findOne({$query:{}, $orderby : {$natural : -1}})。我认为答案中缺少最后一个 parathensis
    • 不应依赖自然秩序;如果您使用的是副本集(并且应该如此),不同的节点很可能会将相同的文档以不同的顺序存储在磁盘上。
    【解决方案6】:

    最后一个函数应该是sort,而不是limit

    例子:

    db.testcollection.find().limit(3).sort({timestamp:-1}); 
    

    【讨论】:

    • 这似乎不正确。为什么sort 会在limit 之后?
    【解决方案7】:

    不能根据集合的大小“跳过”,因为它不会考虑查询条件。

    正确的解决方案是从所需的端点进行排序,限制结果集的大小,然后在必要时调整结果的顺序。

    这是一个基于真实代码的示例。

    var query = collection.find( { conditions } ).sort({$natural : -1}).limit(N);
    
    query.exec(function(err, results) {
        if (err) { 
        }
        else if (results.length == 0) {
        }
        else {
            results.reverse(); // put the results into the desired order
            results.forEach(function(result) {
                // do something with each result
            });
        }
    });
    

    【讨论】:

    • 不错的解决方法!不过,能够在查询级别做同样的事情会很好。类似var query = collection.find( { conditions } ).sort({$natural : -1}).reverse().limit(N)
    【解决方案8】:

    您可能希望使用find 选项: http://docs.meteor.com/api/collections.html#Mongo-Collection-find

    db.collection.find({}, {sort: {createdAt: -1}, skip:2, limit: 18}).fetch();
    

    【讨论】:

      【解决方案9】:

      @bin-chen,

      您可以对集合中文档子集的最新 n 个条目使用聚合。这是一个没有分组的简化示例(在这种情况下,您将在第 4 阶段和第 5 阶段之间进行)。

      这将返回最新的 20 个条目(基于名为“时间戳”的字段),按升序排序。然后它将每个文档 _id、timestamp 和whatever_field_you_want_to_show 投影到结果中。

      var pipeline = [
              {
                  "$match": { //stage 1: filter out a subset
                      "first_field": "needs to have this value",
                      "second_field": "needs to be this"
                  }
              },
              {
                  "$sort": { //stage 2: sort the remainder last-first
                      "timestamp": -1
                  }
              },
              {
                  "$limit": 20 //stage 3: keep only 20 of the descending order subset
              },
              {
                  "$sort": {
                      "rt": 1 //stage 4: sort back to ascending order
                  }
              },
              {
                  "$project": { //stage 5: add any fields you want to show in your results
                      "_id": 1,
                      "timestamp" : 1,
                      "whatever_field_you_want_to_show": 1
                  }
              }
          ]
      
      yourcollection.aggregate(pipeline, function resultCallBack(err, result) {
        // account for (err)
        // do something with (result)
      }
      

      所以,结果看起来像:

      { 
          "_id" : ObjectId("5ac5b878a1deg18asdafb060"),
          "timestamp" : "2018-04-05T05:47:37.045Z",
          "whatever_field_you_want_to_show" : -3.46000003814697
      }
      { 
          "_id" : ObjectId("5ac5b878a1de1adsweafb05f"),
          "timestamp" : "2018-04-05T05:47:38.187Z",
          "whatever_field_you_want_to_show" : -4.13000011444092
      }
      

      希望这会有所帮助。

      【讨论】:

      • 谢谢@lauri108!在此问题和相关问题的所有答案中,这是“如何获得 LAST N DOCS”的唯一可行且可靠的解决方案。并且足够简单,可以在一个查询中完成。工作完成。
      【解决方案10】:
      db.collection.find().hint( { $natural : -1 } ).sort(field: 1/-1).limit(n)
      

      根据mongoDB Documentation

      您可以指定 { $natural : 1 } 以强制查询执行前向集合扫描。

      您还可以指定 { $natural : -1 } 以强制查询执行反向收集扫描。

      【讨论】:

        【解决方案11】:

        使用$slice运算符限制数组元素

        GeoLocation.find({},{name: 1, geolocation:{$slice: -5}})
            .then((result) => {
              res.json(result);
            })
            .catch((err) => {
              res.status(500).json({ success: false, msg: `Something went wrong. ${err}` });
        });
        

        geolocation 是数据数组,我们从中得到最后 5 条记录。

        【讨论】:

          【解决方案12】:

          根据集合的大小,排序、跳过等可能会非常慢。

          如果您的收藏按某些标准编制索引,将会获得更好的性能;然后你可以使用 min() 光标:

          首先,使用db.collectionName.setIndex( yourIndex ) 索引您的收藏 您可以使用升序或降序,这很酷,因为您总是想要“最后 N 个项目”......所以如果您按降序索引,则与获取“前 N 个项目”相同。

          然后你找到你的集合的第一个项目,并使用它的索引字段值作为搜索中的最小条件,例如:

          db.collectionName.find().min(minCriteria).hint(yourIndex).limit(N)
          

          这里是 min() 光标的参考:https://docs.mongodb.com/manual/reference/method/cursor.min/

          【讨论】:

          • 唯一考虑性能的答案,很棒的补充:)
          • 这个答案能保证顺序吗?
          • 显然您可以忘记最小值并使用:db.collectionName.find().hint(yourIndex).limit(N) 如果索引按降序排列,您将获得 N 个最小值。
          • 订单由您的索引保证
          • 很好的答案,应该标记为正确。谢谢
          【解决方案13】:

          你可以试试这个方法:

          获取集合中的总记录数
          db.dbcollection.count() 
          

          然后使用跳过:

          db.dbcollection.find().skip(db.dbcollection.count() - 1).pretty()
          

          【讨论】:

            【解决方案14】:

            如果使用MongoDB compass,可以使用排序字段进行过滤,

            【讨论】:

              【解决方案15】:
               db.collection.find().sort({$natural: -1 }).limit(5)
              

              【讨论】:

              • 我认为最好最简单的答案
              猜你喜欢
              • 1970-01-01
              • 2015-04-29
              • 2015-10-12
              • 1970-01-01
              • 2016-07-15
              • 2010-09-30
              • 1970-01-01
              • 2013-12-31
              相关资源
              最近更新 更多