mongodbコレクションから最大値を取得する方法


87

私は次のようなmongodbコレクションを持っています:

db.kids.find()
//results
[
    {name:'tom', age:10},
    {name:'alice', age:12},
    ....
]

SQLのように、このコレクションからMAX'age 'を取得するにはクエリが必要です。 SELECT MAX(age) FROM kids WHERE 1



9
使用できますdb.collection.find().sort({age:-1}).limit(1)
Vishwas 2015

回答:


125

コメントの1つとして

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

完全に使用可能ですが、パフォーマンスについてはよくわかりません


11
大規模なコレクションの場合は、ageフィールドにインデックスを定義することをお勧めします。次に、を使用するとdb.collection.find({}, {age: 1, _id:0}).sort({age:-1}).limit(1)、おそらく非常に高速な対象クエリが発生します
Ali Dehghani 2016年

@AliDehghaniこの方法はモンゴの破片で機能しますか?
igonejack

72

提案された回答のパフォーマンスは良好です。MongoDBのドキュメントによると:

$ sortが$ limitの直前にある場合、オプティマイザーは$ limitを$ sortに合体させることができます。これにより、ソート操作進行中に上位n件の結果のみを維持できます。ここでnは指定された制限であり、MongoDBはn個のアイテムのみをメモリに格納する必要があります。

バージョン4.0で変更されました。

だからの場合

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

我々は唯一の最高の要素を取得WITHOUTため上記の最適化のコレクションをソートします。


7
そのドキュメントリンクは集約用です。よろしいですfind( ... ).sort( ... ).limit( ... )と同じように扱われますかaggregate([{$match: ... }, {$sort: ...}, {$limit: ...}])?彼らがこれについて言及しているmongoドキュメントの場所はありますか?
jmmut

26

集約フレームワークの使用についてはどうですか?

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

21
これは、sort.limitほど効率的ではありません。それでも、私は深く誰もがその種類と制限について奇妙に感じていることを知っています...
AFP_555 2017年

@ AFP_555集計が並べ替え制限クエリよりも遅いことを知って、本当に驚いています。共有してくれてありがとう!
Nam G VU

1
集計は並べ替え制限クエリよりも遅いですか?
ashusvirus

1
簡単なテストケースを行います。1,000,000個のドキュメント{名前: "プレーヤー"、スコア:x}でコレクションを作成します。.find()。sort({score:-1})。limit(1); .aggregateよりも時間がかかる([{$基:{_id:ヌル、最大:{$最大: "$スコア"}}}])
tuananh

3
@tuananh、これは「スコア」にインデックスがない場合に発生する可能性があります。この場合、sortはO(n log n)操作を実行する必要がありますが、aggregateは1回のスキャンO(n)のみを実行します。インデックス付きフィールドを使用すると、sort(...)。limit(1)は非常に高速な一定時間のO(1)操作になります。
cababunga


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

4
少なくともMongo4.2では、その構文でTypeError: db.collection.findOne(...).sort is not a function。collection.findOne()はドキュメント自体を返すため、そのドキュメントでsort()を呼び出すと機能しないようです。
ピーターハンセン

3

プランを実行することで、オプティマイザーが何をしているかを確認できます。プランを調べる一般的な形式は、MongoDBドキュメントからのものです。すなわちCursor.plan()。本当に深く掘り下げたい場合は、cursor.plan(true)詳細を確認できます。

とは言ってdb.col.find().sort({"field":-1}).limit(1)も、インデックスがある場合は、インデックスがデフォルトで昇順であり、コレクションから最大エントリと1つの値が必要な場合でも、1つのインデックスエントリを読み取ります。

言い換えれば、@ yogeshからの提案は正しいです。

ありがとう-スミット


1

簡単な説明、mongoクエリの応答が以下のようなものであり、配列から最大値のみが必要な場合- >「日付」

{
  "_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クエリを次のように記述できます。

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

1

これは、集約パイプラインを介して実現することもできます。

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

3
これはひどいパフォーマンスを持っています。最高の価値を得るには、常にO(n)指標なしでコストがかかります。これのパフォーマンスはO(n log(n))
sb 2720
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.