Пагинация для RESTful API на Swagger Node

В предыдущей статье мы написали на Swagger Node небольшой простенький API для работы с коллекцией книг. Однако там есть нюанс. Предположим, у нас собралась большая библиотека из нескольких десятков тысяч книг. Каждый раз, когда мы делаем запрос GET /books, наш API отдает полную коллекцию. Это отражается на скорости работы нашего приложения и количестве переданного трафика. Поэтому в этой статье попробуем организовать частичную выдачу книг.

Редактируем API

Для организации постраничной выдачи всех наших книг нам нужно 3 параметра:

  • count - общее количество книг в коллекции;
  • limit - количество книг в одном ответе (показываемых на одной странице);
  • skip - количество пропущенных книг от начала и до первой из текущей выдачи (количество книг на предыдущих страницах).

Зная эти параметры в клиентском приложении легко можно рассчитать общее количество страниц, номер текущей страницы, номера последних страниц.

skip и limit мы будем передавать в качестве параметров запроса. count должен вернуть в ответе сервер.

В файле swagger.yaml в самом конце добавим описания параметров:

parameters:
  skipParam:
    name: skip
    in: query
    description: number of items to skip
    required: false
    type: integer
    format: int32
    minimum: 0
  limitParam:
    name: limit
    in: query
    description: max records to return
    required: false
    type: integer
    format: int32
    maximum: 100
    minimum: 0

Ограничим минимальное значение для skip и limit и максимальное значение для limit. Передавать их будем в query запроса.

Добавим описание схемы для ответа с постраничной выдачей книг в definitions::

Books:
  properties:
    paging:
      type: object
      properties:
        skip:
          type: integer
        limit: 
          type: integer
        count: 
          type: integer
    data:
      type: array
      items:
        $ref: '#/definitions/Book'
  required:
      - paging
      - data

Как видим, теперь ответ сервера должен содержать объект paging с параметрами пагинации и массив с книгами data.

Подправим маршрут GET /books следующим образом:

get:
  description: Return a books list
  parameters:
    - $ref: "#/parameters/skipParam"
    - $ref: "#/parameters/limitParam"
  responses:
    "200":
      description: Success 
      schema:
        $ref: '#/definitions/Books'
    # responses may fall through to errors
    default:
      description: Error
      schema:
        $ref: "#/definitions/ErrorResponse"

Перезапустим сервер в mock-режиме:

swagger project start -m

и попробуем отправить запрос.

Swagger Editor Paging

Работает. Можно браться за контроллер.

Модифицируем контроллер

Заменим код функции getAll на следующий:

function getAll(req, res) {
    var skip = req.swagger.params.skip.value ? req.swagger.params.skip.value : 0;
    var limit = req.swagger.params.limit.value ? req.swagger.params.limit.value : 10;

    Book.find().count(function (err, count) {

        Book.find().skip(skip).limit(limit).exec(function (err, books) {
            if (err) {
                throw err;
            } else {
                res.json({
                        paging: {
                            count: count,
                            skip: skip,
                            limit: limit
                        },
                        data: books
                    }
                );
            }
        });
    });
}

Сперва считываем параметры skip и limit и присваиваем значения по умолчанию, если они не заданы. Затем выполняем запрос в БД для определения общего количества книг count. А потом с заданными параметрами делаем соответствующую выборку книг из БД и отдаем ответ клиенту.

Убедимся, что в swagger.yaml для GET /books задан operationId: getAll. Создадим несколько книг методом POST /books и попробуем поиграться с параметрами пагинации.

Swagger Editor Paging Result

Посмотреть код целиком можно в
этой ветке на гитхабе.

Можете критиковать.

Павел Прудников

Постигающий дзен фулстэк вэб буддизма

Минск, Беларусь

Подписаться на Блог MEAN stack разработчика

Получайте свежие записи прямо на ваш почтовый ящик.

Или подпишитесь на RSS с Feedly!

Комментарии

comments powered by Disqus