Грид, группировка данных и OData

в 16:02, , рубрики: devexpress, devextreme, javascript, json, odata, rest, rest apiful api, RESTful, Веб-разработка, интерфейсы, Программирование

В одной из прошлых статей мы кратко рассказали, как грид контролы работают с удаленным сервером, используя OData протокол. Большинство современных грид контролов позволяют удобно группировать данные по нескольким колонками. Рассмотрим подробнее, как формулируются запросы к REST серверу, в случае, когда грид производит автоматическую группировку данных.

Удобство (зачем это нужно)

Грид контролы, позволяющие группировать записи по нескольким колонкам, существенно упрощают жизнь как программисту, так и конечному пользователю. Очень удобно иметь возможность сгруппировать, например, список задач, выделить задачи, требующие помощи, разделить их по приоритетам, и т.д.

image

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

image

Особенно приятно для разработчиков то, что для создания такого комфортного интерфейса достаточно лишь нескольких строк кода.

Как это сделать

Мы подготовили пример списка задач
nitrosdata.com/samples_devexpress_grouping.html

Для этого примера мы использовали dxDataGrid компании Devexpress (этот грид входит в набор компонентов DevExtreme Web)

Подробнее можно посмотреть в документации dxDataGrid:
js.devexpress.com/Documentation/ApiReference/UI_Widgets/dxDataGrid/
посмотреть примеры:
js.devexpress.com/Demos/WidgetsGallery/#demo/datagridgridpagingandscrollingpager/generic/light/default
простой пример работы грида без группировки с сервером NitrosBase.js:
nitrosdata.com/samples_devexpress_grid.html
Для того чтобы грид работал с NitrosBase.js достаточно указать URL со списком данных для показа в гриде, например, список людей:
nitrosdata.com/service/testdb/person

Для того чтобы включить в гриде группировку, достаточно указать свойство
groupPanel: {visible: true}
После этого грид позволяет группировать данные перетаскивая заголовки колонок на панель группировки.

Чтобы при первом показе грид сгруппировал данные по каким-либо колонкам, необходимо в описании колонок указать:
groupIndex: 0 (для первой колонки, по содержимому которой группируются данные)
groupIndex: 1 (для второй колонки, и т.д.)

Всего пара настроек, и пользователи будут Вам благодарны :)

Как это работает

Мы указали гриду URL по которому он может получить список задач
nitrosdata.com/service/testdb/task

Далее грид автоматически формирует запрос к серверу добавляя к URL различные условия запроса.

Первый запрос, который грид шлет на сервер, для показа списка задач, сгруппированных по статусу и приоритету:
http://nitrosdata.com/service/testdb/task?$orderby=Task_Status,Task_Priority,id&$top=21&$inlinecount=allpages

  • $orderby=Task_Status,Task_Priority – отсортировать записи по статусу и приоритету
  • $top=31 – грид просит ограничить результат и выслать 31 запись
  • $inlinecount=allpages – грид просит вернуть общее количество записей в коллекции

Поскольку данные отсортированы, то в качестве группы он берет значения полей «Task_Status» и «Task_Priority» для первой записи. Далее идут несколько записей с повторяющимися значениями этих полей. Далее идет несколько записей у которых сменился приоритет. То есть в данном случае достаточно простого запроса для получения отсортированных данных.

Если мы будем скролировать грид вниз, чтобы посмотреть остальные записи, грид попросит у сервера следующие записи, например:

http://nitrosdata.com/service/testdb/task?$orderby=Task_Status,Task_Priority,id&$skip=29&$top=32&$inlinecount=allpages

В данном случае добавился еще один параметр запроса:

  • $skip=29 –пропустить указанное количество записей

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

Теперь попробуем схлопнуть группу записей со статусом «Completed». Грид шлёт на сервер 2 запроса:

  1. http://nitrosdata.com/service/testdb/task?$top=1&$filter=(Task_Status eq 'Completed')&$inlinecount=allpages
  2. http://nitrosdata.com/service/testdb/task?$orderby=Task_Status,Task_Priority,id&$top=31&$filter=((Task_Status ne 'Completed'))&$inlinecount=allpages

Первый запрос

  • $filter=(Task_Status eq 'Completed') – отобрать все записи со статусом «Completed» (те что мы схлопываем)
  • $top=1 – грид просит только одну запись
  • $inlinecount=allpages – грид просит вернуть общее количество записей с данным статусом

Этот запрос нужен для того, чтобы узнать количество записей со статусом «Completed» (те что мы схлопываем)

Второй запрос

  • $orderby=Task_Status,Task_Priority – отсортировать данные по указанным полям
  • $filter=(Task_Status ne 'Completed') – отобрать все записи со статусом отличным от «Completed» (те записи, что идут после схлопнутых со статусом «Completed»)
  • $top=31 – грид просит 31 запись
  • $inlinecount=allpages – грид просит вернуть общее количество записей с данным статусом

Если мы схлопываем следующую группу, то первый из этих двух запросов также просит количество записей для схлопываемой группы, а вот следующий запрос теперь уже включает исключения из записей в двух схлопнутых группах:

  • $filter=(Task_Status ne 'Completed') and (Task_Status ne 'Deferred')

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

Замечания (как могло бы работать)

В случае большого количества групп запросы с фильтрацией всех схлопнутых групп, с большим количеством условий на неравенство ($filter=… and … and … and … and … ) становятся слишком большими и недостаточно эффективными.

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

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

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

Автор: NitrosData

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js