Разбивка на страницы агрегированных результатов Mongodb ‘$ group’

#mongodb

#mongodb

Вопрос:

Я создаю API для возврата результатов, сгруппированных с использованием Status.

В MongoDB у меня есть записи, содержащие следующие поля:

 {
  id: Integer,
  Status: String,
  Subject: String,
  Date: Date
}
  

Я использую следующий агрегированный запрос для извлечения результатов, сгруппированных на основе «Статуса».

 db.aggregate([
    {
        $group: {
            _id: '$Status',
            count: { $sum: 1 },
            tickets: { $push: '$$ROOT' }
        }
    }
])
  

Мне нужно показывать только 10 записей в каждой группе одновременно.
Я использую MongoDB 3.6

Как я могу реализовать разбивку на страницы сгруппированных результатов, возвращаемых этим агрегированным запросом?

Ответ №1:

skip(n) пропускает n документов из курсора, в то время как limit (n) ограничивает количество документов, которые должны быть возвращены из курсора. Таким образом, комбинация двух естественным образом разбивает ответ на страницы.

 //Get count from the query params
let limit = parseInt(req.query.count) || 10; 

//Get pageNumber from the query params
let pageNumber = parseInt(req.query.pageNumber) || 1;

if (pageNumber < 1 || limit < 1) res.json([]); // Return empty

let skip = (pageNumber - 1) * limit;

let searchConditions = [ { $group: { _id: '$Status', count: { $sum: 1 }, tickets: { $push: '$$ROOT' } } } ];

db.aggregate(searchConditions)
  .skip(skip)
  .limit(limit)
  

Комментарии:

1. Спасибо за ответ. Но это не разбивка на страницы сгруппированных результатов. После того, как результат агрегированного запроса будет выглядеть следующим образом: [{_id:»Open»,count: 123,tickets:[ {} ] },{_id:»Close»,count: 623,tickets:[ {} ] } ] Массив Tickets в каждой группе будет содержать все билеты этой группы. Я хочу разбить здесь на страницы таким образом, чтобы массив tickets в каждой группе содержал одновременно только 10 билетов, не влияя на количество.

Ответ №2:

Я думаю, что это невозможно сделать во время отправки.

Если приведенный ниже результат неверен, попробуйте с

     Query when pagination button click with skip and limit
  

Попробуйте это. Не знаю, поможет ли это вам.
и я не знаю, правильный ли это метод.

 db.collection.aggregate([
{
    $group: {
        _id: '$Status',
        count: { $sum: 1 },
        tickets: { $push: '$$ROOT' }
    }
},
{
    $addFields:{
        tickets:{ $slice: [ "$tickets", 2,3] }
        }
}
])
  

2,3 — это позиция и количество возвращаемых данных соответственно.
Просто попробуйте.
Я попробую другой метод без среза.

Комментарии:

1. Нарезка будет работать после этапа $ group, верно? Возможно ли это сделать на самом этапе $ group?

2. На самом деле slice это не метод для skip и limit . Здесь slice используется для обозначения количества элементов массива, возвращаемых запросом.

3. У меня около 1 миллиона записей. Для каждого следующего запроса страницы он будет сканировать все 1 миллион записей, и только тогда он будет применять фрагмент правильно?

4. Я думаю, что это невозможно сделать во время отправки. Мы можем выполнить поиск по нему.

5. Да, вы правы. Мне нужна разбивка на страницы на самом этом этапе ($ group). Спасибо за вашу поддержку.