Подтвердить что ты не робот

Запрос на ограничение/смещение Mongoose и счетчик

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

Итак, у меня есть 57 документов в целом, и пользователь хочет, чтобы 10 документов смещались на 20.

Я могу подумать о двух способах этого, сначала это запрос для всех 57 документов (возвращаемых как массив), а затем использование array.slice возвращает нужные им документы. Второй вариант состоит в том, чтобы запустить 2 запроса, первый из которых использует метод count count mongo, а затем запустить второй запрос, используя mongo native $limit и $skip aggregators.

Какой, по вашему мнению, будет лучше масштабироваться? Выполнение всего этого в одном запросе или запуск двух отдельных?

Edit:

// 1 query
var limit = 10;
var offset = 20;

Animals.find({}, function (err, animals) {
    if (err) {
        return next(err);
    }

    res.send({count: animals.length, animals: animals.slice(offset, limit + offset)});
});


// 2 queries
Animals.find({}, {limit:10, skip:20} function (err, animals) {            
    if (err) {
        return next(err);
    }

    Animals.count({}, function (err, count) {
        if (err) {
            return next(err);
        }

        res.send({count: count, animals: animals});
    });
});
4b9b3361

Ответ 1

Я предлагаю вам использовать 2 запроса:

  • db.collection.count() вернет общее количество элементов. Это значение хранится где-то в Монго, и оно не рассчитывается.

  • db.collection.find().skip(20).limit(10) Здесь я предполагаю, что вы можете использовать сортировку по некоторому полю, поэтому не забудьте добавить индекс в это поле. Этот запрос также будет быстрым.

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

Ответ 2

После того, как я сам решил эту проблему, я хотел бы основываться на ответе user854301.

Mongoose ^ 4.13.8 Мне удалось использовать функцию toConstructor() которая позволила мне избежать многократного построения запроса при применении фильтров. Я знаю, что эта функция доступна и в более старых версиях, но вам придется проверить документы Mongoose, чтобы подтвердить это.

Следующее использует обещания Bluebird:

let schema = Query.find({ name: 'bloggs', age: { $gt: 30 } });

// save the query as a 'template'
let query = schema.toConstructor();

return Promise.join(
    schema.count().exec(),
    query().limit(limit).skip(skip).exec(),

    function (total, data) {
        return { data: data, total: total }
    }
);

Теперь запрос подсчета вернет общее количество найденных записей, и возвращенные данные будут подмножеством общих записей.

Обратите внимание на () вокруг query(), который создает запрос.

Ответ 3

Вместо использования 2 запросов используйте агрегат в одном запросе

Совокупность "$ facet" может быть получена быстрее, общее количество и данные с пропуском и лимитом

    db.collection.aggregate([

      //{$sort: {...}}

      //{$match:{...}}

      {$facet:{
        "stage1" : [
           $group:{_id:null, count:{$sum:1}}
         ],

        "stage2" : [
               { "$skip": 0}, {"$limit": 2}
         ]

      }},


     {$unwind: "$stage1"},

      //output projection
     {$project:{
        count: "$stage1.count",
        data: "$stage2"
     }}

 ]);

Вывести следующим образом: -

[{
     count: 50,
     data: [
        {...},
        {...}
      ]
 }]