Списки: страницы, сортировка и фильтры

В документации мы постарались ответить на частые вопросы по работе TesLab, с которыми сталкиваются пользователи.
Если Вы не нашли ответ на свой вопрос, напишите нам.

Личный кабинет

Списки: страницы, сортировка и фильтры

Большой журнал удобно читать небольшими порциями. Эта статья относится к методам, которые принимают startRow, endRow, sortModel и filterModel. Пример использует список заявок ИЛ laboratory/requests/list; состав колонок и дополнительные условия зависят от метода.

В этой статье

Как читать список порциями

  1. Начните с startRow=0 и endRow=25. Сервер вернёт не больше 25 строк.
  2. Задайте разрешённые колонки фильтра и устойчивый порядок, например id desc.
  3. Проверьте HTTP-ответ, затем структуру списка: rows должен быть массивом, счётчики записей должны быть целыми неотрицательными числами. Отсутствие rows не означает пустой список.
  4. Если rows пуст или startRow + rows.length >= recordsFiltered, чтение закончено. При ошибке остановите цикл и обработайте отказ.
  5. Если записи ещё остались, сохраните тот же отбор и порядок, запросите диапазон 25..50, затем 50..75. При изменении фильтра или сортировки начинайте заново с позиции 0.

Позиции относятся к результату отбора, а не к ID записей. При параллельном добавлении, удалении или изменении строк они могут сдвигаться между запросами. Такое чтение не создаёт неподвижный снимок базы; для полного обмена учитывайте возможные повторы и пропуски.

Чтение списка: запросить порцию, проверить ответ и продолжить только при оставшихся строках. При смене отбора начать с нуля.
Сначала проверьте полученную порцию, затем решайте, нужна ли следующая. Правая граница endRow в порцию не входит.

Границы и параметры запроса

ПолеЧто передать
startRow, endRow
Целые числа
Нулевая позиция первой строки и позиция после последней. Размер порции равен endRow-startRow.
sortModel
Массив
Упорядоченный список {colId, sort}, где sort равен asc или desc.
filterModel
Объект
Ключи являются разрешёнными именами колонок, значения задают условия.
page
Целое число
Сопутствующее значение, возвращаемое в ответе. Не рассчитывает смещение и не заменяет границы; без него в показанном методе возвращается 0.
cid
ID заказчика
Дополнительный отбор списка заявок ИЛ по заказчику. Не является универсальным параметром других списков.

Задавайте обе границы явно, начиная с небольшой порции. Используйте неотрицательные целые числа и endRow >= startRow. Равные границы задают пустую порцию. Отсутствие обеих границ может оставить запрос без общего ограничения размера, поэтому не используйте его для обычного постраничного чтения.

Запрос и порядок строк

POST /api/laboratory/requests/list
auth: YOUR_AUTH_TOKEN
Content-Type: application/json
Out: json

{
  "startRow": 0,
  "endRow": 25,
  "page": 1,
  "sortModel": [{"colId": "id", "sort": "desc"}],
  "filterModel": {
    "comment": {"type": "contains", "filter": "Учебная"}
  }
}

Поля id и comment объявлены в этом методе. Экранная подпись «Комментарий» не является именем колонки для API. Неизвестная колонка или неподдержанное условие могут быть пропущены, поэтому проверяйте фактический отбор.

При нескольких элементах sortModel первый имеет наивысший приоритет. Например, следующий порядок сначала сортирует комментарии по возрастанию, затем ID по убыванию:

"sortModel": [
  {"colId": "comment", "sort": "asc"},
  {"colId": "id", "sort": "desc"}
]

Условия фильтра

  • Равно и не равно: equals, notEqual. Например, {"type":"equals","filter":0} сравнивает с числовым нулём.
  • Сравнения: lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual означают меньше, не больше, больше, не меньше. Значение задаётся в filter; тип должен подходить колонке.
  • Диапазон: {"type":"inRange","filter":900100,"filterTo":900200}. Обе границы включены.
  • Текст: contains, notContains, startsWith, endsWith означают содержит, не содержит, начинается, заканчивается.
  • Отсутствующее значение: {"type":"nu"} проверяет SQL NULL, {"type":"nn"} его отсутствие. Значение filter не требуется.
  • Набор: {"filterType":"set","values":[900101,900102]} выбирает одно из указанных значений. Пустой массив values снимает ограничение по колонке.

Разные колонки соединяются логическим AND. Внутри одной колонки можно объединить условия через operator: "AND" или operator: "OR". Например, здесь ID должен входить в набор, а комментарий должен содержать хотя бы одно из двух слов:

"filterModel": {
  "id": {"filterType": "set", "values": [900101, 900102]},
  "comment": {
    "operator": "OR",
    "conditions": [
      {"type": "contains", "filter": "Учебная"},
      {"type": "contains", "filter": "Проверочная"}
    ]
  }
}

Вместо массива conditions поддерживаются condition1 и condition2 с тем же оператором. В набор передавайте значения, ожидаемые методом, например ID или коды статусов, а не экранные подписи.

Текстовый поиск через contains не учитывает регистр и требует каждое слово строки поиска. notContains исключает всю указанную фразу, поэтому не является точным отрицанием многословного contains. Символы % и _ действуют как шаблоны: любая последовательность символов и один символ соответственно. Тип колонки может добавлять подбор раскладки или обработку даты.

NULL и пустая строка различаются. notEqual и notContains сами по себе не включают строки с NULL. Для отсутствующего значения используйте явные nu/nn, а не пустой filter.

Ответ и условие остановки

{
  "records": 120,
  "recordsFiltered": 2,
  "page": 1,
  "rows": [
    {"id": 900102, "comment": "Учебная заявка 2"},
    {"id": 900101, "comment": "Учебная заявка 1"}
  ]
}

records показывает число записей с серверными предметными условиями и областью доступа до пользовательского фильтра. recordsFiltered показывает число после фильтра, rows содержит только текущую порцию. Количество элементов rows не является размером всей выборки.

В примере соблюдён порядок id desc и получены обе подходящие записи: 0 + 2 = recordsFiltered. Чтение закончено, запрос 25..50 не нужен. Он понадобился бы, если бы первая порция содержала 25 строк и после неё оставались данные. Пустая порция за концом списка допустима; её нулевой размер не означает, что сам recordsFiltered равен нулю.

Почему результат отличается от интерфейса

Серверный отбор действует независимо от filterModel. Например, ограниченный доступ к заявкам ИЛ сужает список по автору. Поэтому records не означает число всех записей инсталляции.

При сравнении с интерфейсом проверьте тот же метод, cid, общий поиск, сохранённый вид, фильтры и порядок сортировки. Совпадения одного числа на экране недостаточно: сравните несколько ID и значения колонок.

Проверка перед обменом

Проверьте небольшую выборку: первую порцию, продолжение, пустой результат и отказ API. Используйте разрешённые поля конкретного метода. Пример описывает плоский список; группировка и специальные списки могут иметь другой состав запроса и ответа.

Номера и комментарии в примерах условные. Подставьте свой токен и условия отбора. Обработка ответа и повторные запросы разобраны в связанных материалах ниже.

Связанные материалы