В MongoDB, как получить последние 30 результатов из каждого идентификатора и сгруппировать их по идентификатору

#mongodb #mongoose #mongodb-query

#mongodb #мангуст #mongodb-запрос

Вопрос:

 TestResults Model

    [
    {
_id: "mongoDBObjectId",
testId: "121",
testName: "test1",
result: "pass"
},
{
_id: "mongoDBObjectId",
testId: "122",
testName: "test2",
result: "pass"
},
{
_id: "mongoDBObjectId",
testId: "123",
testName: "test3",
result: "pass"
},
{
_id: "mongoDBObjectId",
testId: "121",
testName: "test1",
result: "fail"
},
{
_id: "mongoDBObjectId",
testId: "121",
testName: "test1",
result: "fail"
},
{
_id: "mongoDBObjectId",
testId: "122",
testName: "test2",
result: "pass"
},
{
_id: "mongoDBObjectId",
testId: "123",
testName: "test3",
result: "fail"
},
]
  

Я должен получить последние 30 документов из каждого «TestID» и сгруппировать их по «TestID»,

 [
{"testId": "121", "testDetails": [{"result": "pass", "testName": "test1"},..]},
{"testId": "122", "testDetails": [{"result": "pass", "testName": "test2"},..]},
{"testId": "123", "testDetails": [{"result": "pass", "testName": "test3"},..]},
]
  

Я пробовал с $match и $group агрегировать, пожалуйста, найдите приведенный ниже код,

 testResults.aggregate([
        {
          $match:
          {
            "testId": { "$exists": true };
          }
        },
        {
          $sort: { _id: -1 },
        },
        {
          $limit: 30
        },
        {
          $group: {
            _id: "$testId",
            testDetails: { $push: {result: "$result", testName: "$testName"} }
          }
        }
      ])
        .exec(function (err, testResults) {
          if (err)
            res.send(err);
    
          res.json(testResults);
        });
  

Приведенный выше код возвращает последние 30 документов из всех «TestID», но я не знаю, как извлечь 30 последних документов из каждого доступного «TestID» и сгруппировать их. А также, я не должен передавать какой-либо конкретный «TestID» или несколько «TestID», я должен извлекать из всех доступных «TestID» в коллекции

Ответ №1:

Вы можете использовать $slice для получения 30 документов за testId ,

  • удалено $limit , потому что это не нужно
  • в последнем $addFields использовать поле $slice в testDetails , чтобы получить 30 лучших элементов, которые мы уже отсортировали ранее,
 testResults.aggregate([
  { $match: { testId: { "$exists": true } } },
  { $sort: { _id: -1 } },
  {
    $group: {
      _id: "$testId",
      testDetails: {
        $push: {
          result: "$result",
          testName: "$testName"
        }
      }
    }
  },
  {
    $addFields: {
      testDetails: { $slice: ["$testDetails", 30] }
    }
  }
])
.exec(function (err, testResults) {
  if (err) res.send(err);
  res.json(testResults);
});
  

Игровая площадка