mongodb如何从集合中获取最大价值


Answers:


118

作为评论之一

db.collection.find().sort({age:-1}).limit(1) // for MAX
db.collection.find().sort({age:+1}).limit(1) // for MIN

它是完全可用的,但我不确定性能


9
如果集合很大,最好在age字段上定义一个索引。然后,如果使用db.collection.find({}, {age: 1, _id:0}).sort({age:-1}).limit(1),则可能会有一个非常快速的Covered Query
Ali Dehghani

@AliDehghani这种方法对mongo碎片有效吗?
igonejack,

68

建议答案的效果很好。根据MongoDB文档

当$ sort紧接在$ limit之前时,优化程序可以将$ limit合并到$ sort中。这允许排序操作在执行过程中仅保留前n个结果,其中n是指定的限制,而MongoDB仅需要在内存中存储n个项目。

在版本4.0中更改。

所以在

db.collection.find().sort({age:-1}).limit(1)

由于提到的优化,我们只获得最高的元素而无需对集合进行排序。


6
该文档链接用于汇总。您确定find( ... ).sort( ... ).limit( ... )与对待方式相同aggregate([{$match: ... }, {$sort: ...}, {$limit: ...}])吗?他们在mongo文档中有没有提到这一点的地方?
jmmut

25

如何使用聚合框架:

db.collection.aggregate({ $group : { _id: null, max: { $max : "$age" }}});

18
这不如sort.limit有效。不过,我深知每个人都对这种排序和限制感到奇怪...
AFP_555'3

@ AFP_555真的很惊讶得知聚合比排序限制查询要慢。感谢分享!
Nam G VU

1
聚合比排序限制查询慢吗?
ashusvirus

1
我做一个简单的测试用例。用1,000,000个文档{名称:“玩家”,得分:x}创建一个集合。.find()。sort({score:-1})。limit(1); 比.aggregate([{$ group:{_id:null,max:{$ max:“ $ score”}}}])的时间
更长

3
@tuananh,如果您没有“分数”的索引,则可能会发生这种情况。在这种情况下,排序将必须执行O(n log n)操作,而聚合仅执行一次扫描O(n)。使用索引字段,sort(...)。limit(1)将是非常快速的恒定时间O(1)操作。
cababunga


3

人们可以通过运行计划来查看优化器的工作。查看计划的通用格式来自MongoDB文档。即Cursor.plan()。如果您真的想更深入,可以执行cursor.plan(true)以获得更多详细信息。

话虽如此,如果您有索引,则db.col.find()。sort({“ field”:-1})。limit(1)将读取一个索引条目-即使该索引默认为默认升序并且您想要最大条目和集合中的一个值。

换句话说,@ yogesh的建议是正确的。

谢谢-Sumit


2
db.collection.findOne().sort({age:-1}) //get Max without need for limit(1)

4
至少在Mongo 4.2中,该语法会让您获得TypeError: db.collection.findOne(...).sort is not a function。collection.findOne()返回文档本身,因此调用sort()似乎不太可行。
Peter Hansen

1

简单说明,如果您有mongo查询,则响应如下所示-并且您只希望Array->“ Date”中的最大值

{
  "_id": "57ee5a708e117c754915a2a2",
  "TotalWishs": 3,
  "Events": [
    "57f805c866bf62f12edb8024"
  ],
  "wish": [
    "Cosmic Eldorado  Mountain Bikes, 26-inch (Grey/White)",
    "Asics Men's Gel-Nimbus 18 Black, Snow and Fiery Red Running Shoes - 10 UK/India (45 EU) (11 US)",
    "Suunto Digital Black Dial Unisex Watch - SS018734000"
  ],
  "Date": [
    "2017-02-13T00:00:00.000Z",
    "2017-03-05T00:00:00.000Z"
  ],
  "UserDetails": [
    {
      "createdAt": "2016-09-30T12:28:32.773Z",
      "jeenesFriends": [
        "57edf8a96ad8f6ff453a384a",
        "57ee516c8e117c754915a26b",
        "58a1644b6c91d2af783770b0",
        "57ef4631b97d81824cf54795"
      ],
      "userImage": "user_profile/Male.png",
      "email": "roopak@small-screen.com",
      "fullName": "Roopak Kapoor"
    }
  ],

},

***然后添加

Latest_Wish_CreatedDate:{$ max:“ $ Date”},

像下面这样

{ 
                $project : { _id: 1,
                             TotalWishs : 1 ,
                              wish:1 ,
                               Events:1, 
                               Wish_CreatedDate:1,
                               Latest_Wish_CreatedDate: { $max: "$Date"},
                            } 
            } 

最终查询响应将在下面

{
  "_id": "57ee5a708e117c754915a2a2",
  "TotalWishs": 3,
  "Events": [
    "57f805c866bf62f12edb8024"
  ],
  "wish": [
    "Cosmic Eldorado  Mountain Bikes, 26-inch (Grey/White)",
    "Asics Men's Gel-Nimbus 18 Black, Snow and Fiery Red Running Shoes - 10 UK/India (45 EU) (11 US)",
    "Suunto Digital Black Dial Unisex Watch - SS018734000"
  ],
  "Wish_CreatedDate": [
    "2017-03-05T00:00:00.000Z",
    "2017-02-13T00:00:00.000Z"
  ],
  "UserDetails": [
    {
      "createdAt": "2016-09-30T12:28:32.773Z",
      "jeenesFriends": [
        "57edf8a96ad8f6ff453a384a",
        "57ee516c8e117c754915a26b",
        "58a1644b6c91d2af783770b0",
        "57ef4631b97d81824cf54795"
      ],
      "userImage": "user_profile/Male.png",
      "email": "roopak@small-screen.com",
      "fullName": "Roopak Kapoor"
    }
  ],
  "Latest_Wish_CreatedDate": "2017-03-05T00:00:00.000Z"
},

1

对于最大值,我们可以将sql query编写为

select age from table_name order by age desc limit 1

我们也可以用mongodb编写相同的方法。

db.getCollection('collection_name').find().sort({"age" : -1}).limit(1); //max age
db.getCollection('collection_name').find().sort({"age" : 1}).limit(1); //min age

0

您也可以通过聚合管道来实现。

db.collection.aggregate([{$sort:{age:-1}}, {$limit:1}])

2
这有一个糟糕的表现。取得最高价值总O(n)要付出代价,而没有指标。这具有O(n log(n))
sb27
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.