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

답변:


125

의견 중 하나로 :

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), 당신은 아마 매우 빠른 것 대상 쿼리
알리 Dehghani

@AliDehghani이 방법은 몽고 샤드에서 작동합니까?
igonejack

72

제안 된 답변의 성능이 좋습니다. MongoDB 문서 에 따르면 :

$ sort가 $ limit 바로 앞에 오면 옵티마이 저는 $ limit를 $ sort로 통합 할 수 있습니다. 이렇게하면 정렬 작업이 진행되는 동안 상위 n 개의 결과 만 유지할 수 있습니다 . 여기서 n은 지정된 제한입니다. 이고 MongoDB는 메모리에 n 개의 항목 만 저장하면됩니다.

버전 4.0에서 변경되었습니다.

그래서의 경우

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

우리는 가장 높은 요소를 얻을 없이 때문에 언급 한 최적화의 컬렉션을 정렬.


7
그 문서 링크는 집계 용입니다. 당신은시겠습니까 find( ... ).sort( ... ).limit( ... )과 같은 방식으로 처리됩니다 aggregate([{$match: ... }, {$sort: ...}, {$limit: ...}])? 몽고 문서에 그들이 이것을 언급하는 곳이 있습니까?
jmmut

26

집계 프레임 워크 사용은 어떻습니까?

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

21
이것은 sort.limit만큼 효율적이지 않습니다. 그래도, 내가 아는 깊은 모두가 ... 그런 종류 및 제한에 대한 이상한 느낌
AFP_555

@ AFP_555 집계가 정렬 제한 쿼리보다 느리다는 사실에 정말 놀랐습니다. 공유해 주셔서 감사합니다!
Nam G VU

1
집계가 정렬 제한 쿼리보다 느립니까?
ashusvirus

1
간단한 테스트 케이스를 수행합니다. 1,000,000 개의 문서 {이름 : "플레이어", 점수 : x}로 컬렉션을 만듭니다. .find (). sort ({score : -1}). limit (1); .aggregate보다 더 많은 시간이 걸립니다 ([{$ 그룹 : {_id : 널 (null), 최대 : {$ 최대 : "$ 점수"}}}])
tuananh

3
@tuananh, "점수"에 대한 색인이없는 경우 발생할 수 있습니다. 이 경우 정렬은 O (n log n) 작업을 수행해야하는 반면 집합체는 O (n) 한 번의 스캔 만 수행합니다. 인덱싱 된 필드를 사용하면 sort (...). limit (1)은 매우 빠른 상수 시간 O (1) 작업입니다.
cababunga

10

그룹 및 최대를 사용할 수 있습니다.

db.getCollection('kids').aggregate([
    {
        $group: {
            _id: null,
            maxQuantity: {$max: "$age"}
        }
    }
])

거의 1 년 전에 같은 대답 이 이미 주어졌습니다.
Dan Dascalescu

1
다른 비슷한 대답이 작동하지 않는 것 -이 구문을 수행합니다
자크 스미스

3
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

3

여러분은 계획을 실행하여 최적화 프로그램이 수행하는 작업을 볼 수 있습니다. 계획을 살펴 보는 일반적인 형식은 MongoDB 문서 에서 가져온 것 입니다. 즉 Cursor.plan(). 정말로 더 깊이 파고 싶다면 cursor.plan(true)더 자세한 내용을 위해 할 수 있습니다 .

당신은 인덱스가있는 경우, 당신했다 가졌 db.col.find().sort({"field":-1}).limit(1)인덱스는 기본적으로 상승하는 경우에도 당신이 컬렉션에서 최대 입력과 하나 개의 값을 원 - 하나 개의 인덱스 항목을 읽습니다.

즉, @yogesh의 제안이 정확합니다.

감사합니다-Sumit


1

간단한 설명, 아래와 같은 몽고 쿼리 응답 이 있고 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 쿼리를 다음과 같이 작성할 수 있습니다.

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))
sb27
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.