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

При работе с Node.js и MongoDB есть два общих шаблона для создания пагинации:

  • используйте .skip(X).limit(Y) при запросе данных: в основном мы определяем размер страницы («лимит») и играем с вычислением значения «пропустить»
  • используйте {_id: {$lt: FIRST_MONGO_ID, $gt: LAST_MONGO_ID}} и .sort(_id: -1}: здесь мы сохраняем ссылку на первый и последний показанные элементы и всегда играем с поиском элементов между этими значениями

Некоторые статьи, говорящие об этом:

Вот проблема, которая у нас есть: разбитый на страницы список элементов из двух разных коллекций монго, одна из которых содержит около 400 000 элементов, а другая - почти 2 миллиона элементов. По мере роста количества элементов увеличивается и время запроса. Давайте посмотрим некоторые цифры.

Для первой страницы:

  • время запроса: 16,37 с
  • ответ: {items: [...], page: 1, pageSize: 10, total: 14225}

Для последней страницы:

  • время запроса: 37,61 с
  • ответ: {items: [...], page: 1426, pageSize: 10, total: 14255}

Немного подробностей о реализации:

  • skip + limit — используемая здесь стратегия нумерации страниц.
  • мы вычисляем общее количество элементов, которые будут соответствовать запросу, даже если мы возвращаем только определенный размер страницы * количество страниц, которые мы хотим возвращать каждый раз

Улучшение было основано на функциональных и технических изменениях.

Функциональные изменения были основаны на том, как обрабатывать длинный список результатов. Например, когда вы ищете что-то слишком общее в Google, вы сначала не получите все доступные страницы (общее количество элементов), но вы получите определенное их количество, и когда вы продвигаетесь вперед по списку, вы получить новые страницы (другое количество элементов). Это имеет смысл, потому что вы заплатите высокую цену (время на расчет всех доступных элементов) за то, что, вероятно, не понадобится. Если элементов слишком много, следует улучшить условия поиска и получить меньше элементов.

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

  • иметь правильные индексы и выполнять запрос на основе этих полей
  • использовать проекцию в запросе. Не получайте все элементы из коллекции. Получите только те свойства, которые вам понадобятся для списка (когда вам понадобятся остальные свойства, просто выполните простой запрос по идентификатору и получите их)
  • каждый раз ищем ограниченное количество элементов для обновления итога, в моем случае 100 элементов (что означает 10 страниц по 10 элементов). Код что-то вроде

Давайте посмотрим на улучшение времени запроса

Для первой страницы:

  • время запроса: 732 мс
  • ответ: {items: [...], page: 1, pageSize: 1, total: 100}

Для последней видимой страницы (при загрузке появится другая):

  • время запроса: 1,87 с
  • ответ: {items: [...], page: 20, pageSize: 10, total: 542}

Понятно, что улучшение очень высокое и это слишком производительность для клиента.

Итак, как мы видим, функциональные изменения важнее технических. Каждый раз нам нужно оценивать, как мы собираемся использовать технологию, чтобы получить лучшее решение для пользователей. В этом случае сокращение времени на отображение данных важнее, чем сообщение пользователю, сколько всего элементов у нас есть (у нас их так много, что это становится менее важным, чем правильный ответ по времени). Нам не нужно каждый раз вносить большие и сложные технические изменения, возможно, нам нужно чаще «думать нестандартно».

Надеюсь, это поможет кому-то.

Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Получите эксклюзивный доступ к возможностям написания и советам в нашем сообществе Discord.