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

$ skip и $limit в структуре агрегации

Когда я прочитал документ, я нашел следующие примечания:

Когда $sort немедленно предшествует предел $в конвейере, операция сортировки $сохраняет только верхние n результатов по мере их продвижения, где n - указанный предел, а MongoDB нужно хранить только n элементов в памяти. Эта оптимизация по-прежнему применяется, когда allowDiskUse истинно, а n элементов превышают предел памяти агрегации.

Если я прав, это применимо только тогда, когда я использую $sort и $limit вместе, например

db.coll.aggregate([
    ...,
    {$sort: ...},
    {$limit: limit},
    ...
]);

Однако, я думаю, что большую часть времени у нас было бы

db.coll.aggregate([
    ...,
    {$sort: ...},
    {$skip: skip},
    {$limit: limit},
    ...
]);

Вопрос 1: Означает ли это, что правило выше не применяется, если я использую здесь $skip?

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

Вопрос 2. Нужно ли мне изменить свой запрос на следующее, чтобы повысить производительность?

db.coll.aggregate([
    ...,
    {$sort: ...},
    {$limit: skip + limit},
    {$skip: skip},
    {$limit: limit},
    ...
]);

РЕДАКТИРОВАТЬ. Я думаю, что объясняет, что мой вариант использования сделает вопрос выше более разумным. Я использую функцию текстового поиска, предоставленную MongoDB 2.6 для поиска продуктов. Я беспокоюсь, если пользователь вводит очень распространенное ключевое слово, например "красный", слишком много результатов будет возвращено. Таким образом, я ищу лучшие способы генерации этого результата.

EDIT2: Оказывается, последний код выше равен

db.coll.aggregate([
    ...,
    {$sort: ...},
    {$limit: skip + limit},
    {$skip: skip},
    ...
]);

Таким образом, мы всегда можем использовать эту форму, чтобы применить правило top n.

4b9b3361

Ответ 1

Поскольку это текстовый поисковый запрос, о котором мы говорим, тогда наиболее оптимальная форма такова:

db.collection.aggregate([
    { "$match": {
        "$text": { "$search": "cake tea" }
    }},
    { "$sort": { "score": { "$meta": "textScore" } },
    { "$limit": skip + limit },
    { "$skip": skip }
])

Обоснование резерва памяти из лучших результатов сортировки будет работать только в пределах своих собственных "пределов", и это не будет оптимальным ни для чего, кроме нескольких разумных "страниц" данных.

Помимо разумного для потребления памяти, дополнительный этап, скорее всего, будет иметь отрицательный эффект, а не положительный.

Это действительно практические ограничения возможностей текстового поиска, доступные MongoDB в текущей форме. Но для чего-то более подробного и требующего большей производительности, то, как и в случае со многими "полными текстовыми" решениями SQL, вам лучше использовать внешнее "специально построенное" решение для поиска текста.

Ответ 2

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

db.unicorns.find()
.sort({weight: -1})
.limit(2)
.skip(1)

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