Выберите первые n элементов из каждого массива, упорядоченного по описанию

Рассмотрим коллекцию со следующими документами:

{
    "_id" : 1,
    "name" : "Class 1",
    "students" : [  
        { "rollNo" : 10001, "name" : "Ram", "score" : 65 },
        { "rollNo" : 10002, "name" : "Shyam", "score" : 90 }, <=
        { "rollNo" : 10003, "name" : "Mohan", "score" : 75 }  <=
    ]
},
{
    "_id" : 2,
    "name" : "Class 2",
    "students" : [  
        { "rollNo" : 20001, "name" : "Krishna", "score" : 88 },
        { "rollNo" : 20002, "name" : "Sohan", "score" : 91 }, <=
        { "rollNo" : 20003, "name" : "Radhika", "score" : 82 },
        { "rollNo" : 20004, "name" : "Komal", "score" : 55 },
        { "rollNo" : 20005, "name" : "Sonam", "score" : 91 }  <=        
    ]
},
{
    "_id" : 3,
    "name" : "Class 3",
    "students" : [  
        { "rollNo" : 30001, "name" : "Monika", "score" : 77 }, <=
        { "rollNo" : 30002, "name" : "Rahul", "score" : 81 }   <=
    ]
}

Моя цель состоит в том, чтобы получить N лучших студентов из каждого массива, упорядоченных по убыванию баллов (рассмотрите 2 лучших студентов в порядке убывания баллов).

Мой ожидаемый результат:

Выберите первые n элементов из каждого массива, упорядоченного по описанию

Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
1
0
431
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вам просто нужны записи учеников без группировки, вы можете просто $unwind, а затем $sort:

db.collection.aggregate([
  { $unwind: "$students" },
  { $sort: { "students.score": -1 } },
  { $limit: 2 }
])

Однако это оставит объект students. Для более чистого вывода вы можете использовать $replaceRoot с $mergeObjects:

db.collection.aggregate([
  { $unwind: "$students" },
  { $sort: { "students.score": -1 } },
  { $replaceRoot: {
      newRoot: {
        $mergeObjects: [ { _id: "$_id", class: "$name" }, "$students" ]
      }
    }
  },
  { $limit: 2 }
])

Посмотреть здесь работают

Это даст вам следующий результат:

[
  {
    "_id": 2,
    "class": "Class 2",
    "name": "Sonam",
    "rollNo": 20005,
    "score": 91
  },
  {
    "_id": 2,
    "class": "Class 2",
    "name": "Sohan",
    "rollNo": 20002,
    "score": 91
  }
]

ОБНОВИТЬ:

Используйте это, чтобы получить 2 лучших для каждой группы:

db.collection.aggregate([
  { $unwind: "$students" },
  { $sort: { "students.score": -1 }
  },
  {
    $group: {
      "_id": "$_id",
      "name": { $first: "$name" },
      "students": { $push: "$students" }
    }
  },
  {
    "$project": {
      "top_two": { "$slice": [ "$students", 2 ] }
    }
  }
])

Посмотреть здесь работают

пожалуйста, посмотрите на ожидаемый результат. Я обновил его для лучшего понимания.

saif 30.06.2019 13:55

Это ожидаемый результат, который я ищу. Спасибо

saif 01.07.2019 06:31

Начиная с Mongo 5.2, это хороший пример использования новых операторов агрегирования $sortArray и $firstN:

// { students: [
//    { name: "Ram",   score: 65 },
//    { name: "Shyam", score: 90 },
//    { name: "Mohan", score: 75 }
// ]}
// { students: [
//    { name: "Krishna", score: 88 },
//    { name: "Sohan",   score: 91 },
//    { name: "Radhika", score: 82 },
//    { name: "Komal",   score: 55 },
//    { name: "Sonam",   score: 91 }
// ]}
// { students: [
//    { name: "Monika", score: 77 },
//    { name: "Rahul",  score: 81 }
// ]}
db.collection.aggregate(
  { $set: { students: {
    $firstN: {
      n: 2,
      input: { $sortArray: { input: "$students", sortBy: { score: -1 } } }
    }
  }}}
)
// { students: [
//    { name: "Shyam", score: 90 },
//    { name: "Mohan", score: 75 }
// ]}
// { students: [
//    { name: "Sohan", score: 91 },
//    { name: "Sonam", score: 91 }
// ]}
// { students: [
//    { name: "Rahul", score: 81 },
//    { name: "Monika", score: 77 }
// ]}

Этот:

  • сортирует ($sortArray) каждый students массив по score
  • чтобы получить первых 2 ($firstN) студентов

Другие вопросы по теме