mongodb як отримати максимальне значення з колекцій


87

У мене є колекція mongodb, така як:

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

Мені потрібен запит, щоб отримати MAX-вік із цієї колекції, як у SQL: 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), у вас, мабуть, буде дуже швидкий критий запит
Алі Дехгані

@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: ...}])? чи є де-небудь в документах mongo, де вони згадують про це?
jmmut

26

як щодо використання агрегованого фреймворку:

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

21
Це не настільки ефективно, як sort.limit. Тим не менше, я знаю, що в глибині
душі

@ AFP_555 Дійсно здивований, дізнавшись, що агрегат повільніший за запит з обмеженням сортування. Дякую, що поділились!
Nam G VU

1
агрегат повільніший за запит з обмеженням сортування?
ашусвірус

1
Я роблю простий тест. Створіть колекцію з 1 000 000 документів {name: "player", score: x}. .Find (). Sort ({score: -1}). Limit (1); займе більше часу, ніж .aggregate ([{$ group: {_id: null, max: {$ max: "$ score"}}}])
tuananh

3
@tuananh, це може статися, якщо у вас немає індексу на "бал". У цьому випадку сортування доведеться виконувати операції O (n log n), тоді як агрегат виконуватиме лише одне сканування O (n). З індексованим полем сортування (...). Limit (1) буде дуже швидким постійним часом роботи O (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 є правильними.

Дякую - Суміт


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 як

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.