Записи и коллекции. Рекурсивная выборка записей из иерархических коллекций с помощью N3
Введение
Атрибут типа «Запись» хранит ID записей в связанном шаблоне (ссылки на них).
Зачастую требуется предоставлять пользователю для выбора списки записей, объединённые из нескольких шаблонов и отфильтрованные по сложным правилам. Например, когда данные находятся в иерархически связанных справочниках.
Для работы с иерархическими структурами в N3 доступны две функции обхода иерархии:
object:getRootByParentProperty— выполняет восходящий обход иерархии (от дочерней записи к корневой через цепочку родительских записей) и возвращает корневую запись;object:getRootByChildProperty— выполняет нисходящий обход иерархии (от текущей записи по цепочке ко всем дочерним) и возвращает список всех найденных дочерних записей.
Здесь представлены примеры использования этих функций для выборки записей из иерархических коллекций.
Прикладная задача
-
В системе кадрового учёта имеется следующая иерархическая оргструктура:
Компания└── Департамент└── Сотрудники компании└── Отдел└── Сотрудники департамента└── Группа└── Сотрудники отдела -
Любое подразделение может содержать ссылки на произвольное количество дочерних подразделений и аккаунтов сотрудников.
Требуется:
- Найти корневое подразделение (Компанию), начиная от выбранного подразделения и двигаясь вверх по иерархии (восходящий обход).
- Найти все дочерние подразделения, начиная от выбранного подразделения и двигаясь вниз по иерархии (нисходящий обход).
- Получить список всех сотрудников, работающих в найденных подразделениях.
Исходные данные
Имеются шаблоны записей «Оргструктура» и «Сотрудники».
-
В шаблоне записи «Оргструктура» хранится организационная структура компании.
Атрибуты в шаблоне:
- Родительское подразделение
- Описание: Ссылка на родительское подразделение в иерархии
- Тип данных: запись
- Связанный шаблон: Оргструктура
- Хранить несколько значений: флажок снят
- Дочернее подразделение
- Описание: Коллекция дочерних подразделений в иерархии
- Тип данных: запись
- Связанный шаблон: Оргструктура
- Хранить несколько значений: флажок установлен
- Сотрудники
- Описание: Коллекция сотрудников, работающих в подразделении
- Тип данных: запись
- Связанный шаблон: Сотрудники
- Хранить несколько значений: флажок установлен
- В шаблоне записи «Сотрудники» хранится информация о сотрудниках организации.
Атрибуты в шаблоне:
- Подразделение
- Описание: Ссылка на подразделение, в котором работает сотрудник
- Тип данных: запись
- Связанный шаблон: Оргструктура
- Хранить несколько значений: флажок снят
- Аккаунт
- Описание: Ссылка на аккаунт сотрудника
- Тип данных: аккаунт
- Связанный шаблон: Сотрудники
- Хранить несколько значений: флажок снят
Практический пример: получение компании, к которой относится текущее подразделение
Для вычисления корневого подразделения воспользуемся функцией восходящего обхода иерархической коллекции записей object:getRootByParentProperty.
- Откройте шаблон записи «Оргструктура».
- Создайте атрибут «Компания» со следующими свойствами:
- Описание: Компания
- Тип данных: запись
- Связанный шаблон: Оргструктура
- Хранить несколько значений: флажок снят
- Вычислять автоматически: флажок установлен
-
Введите следующее вычисляемое значение на языке N3:
@prefix object: <http://comindware.com/ontology/object#>.{# Убедитесь, что системные имена соответствуют именам в вашем приложении.# Получаем атрибут, который ссылается на родительское подразделение("Оргструктура" "Родительскоеподразделение") object:findProperty ?ParentDepartmentAttribute.# Получаем корневую запись с помощью восходящего обхода# родительских записей от текущей записи (?item)(?item ?ParentDepartmentAttribute) object:getRootByParentProperty ?RootDepartment.# Возвращаем корневую запись?RootDepartment -> ?value.} -
Поместите атрибут «Компания» на форму шаблона «Оргструктура».
Логика работы функции object:getRootByParentProperty
Функция object:getRootByParentProperty обходит цепочку родительских записей от текущей записи, пока не найдёт запись без родительской записи (то есть корневую запись) и возвращает найденную корневую запись.
-
Синтаксис:
(?startRecord ?parentAttribute) object:getRootByParentProperty ?returnValue. -
Аргументы:
?startRecord— начальная запись, от которой начинается обход;?parentAttribute— атрибут, ссылающийся на родительскую запись;?returnValue— возвращаемое значение.
-
Пример иерархии при восходящем обходе:
Компания (корневая запись)└─ Департамент└─ Отдел└─ Группа (начальная запись — ?startRecord)При вызове функции с начальной записью «Группа» функция вернёт запись «Компания».
Практический пример: получение списка всех сотрудников текущего подразделения и его дочерних подразделений
Для получения списка всех сотрудников, работающих в текущем подразделении и всех его дочерних подразделениях, воспользуемся функцией нисходящего обхода иерархической коллекции записей object:getRootByChildProperty.
- Откройте шаблон записи «Оргструктура».
- Создайте атрибут «Все сотрудники» со следующими свойствами:
- Описание: Список всех сотрудников в текущем подразделении и всех его дочерних подразделениях
- Тип данных: запись
- Связанный шаблон: Сотрудники
- Хранить несколько значений: флажок установлен
- Вычислять автоматически: флажок установлен
-
Введите следующее вычисляемое значение на языке N3:
@prefix object: <http://comindware.com/ontology/object#>.@prefix list: <http://www.w3.org/2000/10/swap/list#>.{# Убедитесь, что системные имена соответствуют именам в вашем приложении.# Получаем атрибуты для дальнейших вычислений("Оргструктура" "Дочернееподразделение") object:findProperty ?ChildDepartmentAttribute.("Оргструктура" "Сотрудники") object:findProperty ?EmployeesAttribute.# Получаем все дочерние подразделения с помощью нисходящего обхода# от текущей записи (?item) до конечной без дочерних подразделений(?item ?ChildDepartmentAttribute) object:getRootByChildProperty ?ChildDepartments.# Получаем всех сотрудников из всех найденных подразделений?ChildDepartments ?EmployeesAttribute ?Employees.# Возвращаем список найденных сотрудников?Employees -> ?value.} -
Поместите атрибут «Все сотрудники» на форму шаблона «Оргструктура».
Логика работы функции object:getRootByChildProperty
Функция object:getRootByChildProperty последовательно обходит цепочку дочерних записей от текущей записи, пока не встретит запись, у которой отсутствует дочерняя запись (то есть конечную запись). Функция возвращает список всех дочерних записей, найденных при обходе.
-
Синтаксис:
(?startRecord ?childAttribute) object:getRootByChildProperty ?returnValue. -
Аргументы:
?startRecord— текущая запись, от которой начинается обход;?childAttribute— атрибут, ссылающийся на дочерние записи;?returnValue— возвращаемое значение (список дочерних записей).
-
Пример иерархии для нисходящего обхода:
Компания (начальная точка — ?item)└─ Департамент└─ Отдел└─ ГруппаПри вызове функции с начальной записью «Компания» функция вернёт список:
[Компания, Департамент, Отдел, Группа].
Эта статья была полезна 1 чел.