Сергей Тачков
Сергей Тачков
20 мар. 2026 г., 18:44
34

XQuery: раскрываем потенциал

РазработкаXQueryСистемное администрированиеДизайнер

О чём эта статья

Многие разработчики привыкли использовать для работы с данными прямые SQL запросы, но что делать, если ты разрабатываешь какой-либо универсальный компонент, который должен работать на разных базах данных, или ты знаешь о грядущем переезде на другую базу данных?

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

Варианты выполнения запросов к базе данных

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

Интерфейс в приложении администратора

Если мы хотим быстро что-то посмотреть в базе данных, можно использовать специализированный инструмент, доступный в приложении администратора. Для его открытия необходимо нажать на иконку Шестерёнки в левом нижнем углу, выбрать пункт меню Поиск и подпункт По каталогам..., после чего у нас откроется интерфейс для формирования XQuery запроса.

Screenshot 2026-03-20 at 09.13.03.png
Интерфейс для выполнения XQuery запросов

Данный интерфейс позволяет нам как ввести запрос напрямую в поле XQuery, предварительно поставив галочку слева от названия поля, так и собрать запрос по частям, используя соответствующие поля ввода. При этом, когда мы заполняем поля с условиями, итоговый запрос автоматически прописывается в поле XQuery, что можно увидеть на скриншоте ниже - этот запрос можно скопировать и использовать в своём программном коде.

Screenshot 2026-03-20 at 11.45.24.png
Пример заполнения полей и вывод данных

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

Screenshot 2026-03-20 at 13.25.24.png
Интерфейс редактирования фильтра

Данные условия так же можно использовать в поле Условие XQuery (относительно $elem) в полях с типом Ссылка на объект в базе и некоторых выборках, позволяющих указать дополнительные условия, но это уже тема для другой статьи.

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

Вызов из программного кода

Если же нам необходимо сделать запрос к базе данных из программного кода, мы можем использоваться прямой вызов функции XQuery, или же использовать обёртку tools.xquery() - которая позволит нам применять дополнительные конструкции в запросе.

Важно помнить, что запрос выполнится только в том случае, если вы обращаетесь к его результатам

Функции в XQuery

В XQuery реализован ряд функций для упрощения выполнения выборки данных из базы.

Сontains

Функция предназначена для проверки вхождения подстроки в строку, другими словами, с помощью неё можно проверить содержит ли какое-то поле искомое нами значение.

Например, найдём сотрудников, у которых в поле code содержится значение F_:

for $elem in collaborators where contains($elem/code, "F_") return $elem

И обратный пример с выбором сотрудников, у которых в поле code отсутствует подстрока F_:

for $elem in collaborators where contains($elem/code, "F_") = false() return $elem

Doc-contains

Функция предоставляет возможность выполнять полнотекстовый поиск по документам - это довольно мощный инструмент, если уметь им правильно пользоваться.

Стандартный поиск

Простой пример поиска сотрудников с наличием в карточке слова Симинюк:

for $elem in collaborators where doc-contains($elem/id, "wt_data", "Симинюк") return $elem

И обратный пример, найдём всех сотрудников, у которых данное слово не встречается:

for $elem in collaborators where doc-contains($elem/id, "wt_data", "Симинюк") = false() return $elem

Также поддерживается поиск по конкретной фразе:

for $elem in collaborators where doc-contains($elem/id, "wt_data", "[Симинюк]") return $elem

И поиск по словоформам, который включается путём добавления символа ` в конец искомого значения, но для этого требуется дополнительная настройка:

for $elem in document where doc-contains($elem/id, "wt_data", "отдела`", "document") return $elem

Поиск по настраиваемым полям

Также данная функция позволяет искать значения по Настраиваемым полям в карточке объекта, например, мы можем найти все записи, в которых значение настраиваемого поля с кодом some_string_field содержит Искомое значение:

for $elem in collaborators where doc-contains($elem/id, "wt_data", "[some_string_field contains Искомое значение~string]") return $elem

Или, например, найти все записи, в которых значение настраиваемого поля с кодом some_date_field, имеющего тип Дата, меньше даты 2026-03-20:

for $elem in collaborators where doc-contains($elem/id, "wt_data", "[custom_field_name>2026-03-20~date]") return $elem

Fields

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

В примере мы возвращаем только id и email сотрудника, игнорируя остальные столбцы:

for $elem in collaborators return $elem/Fields("id", "email")

Мы не можем одновременно использовать конструкцию с $elem/Fields() и $elem/__data - только что-то одно.

ForeignElem

Функция позволяет нам обратиться к связанному объекту прямо внутри текущего запроса.

Для примера, найдём всех действующих сотрудников, которые прикреплены за действующими подразделениями:

for $elem in collaborators where $elem/is_dismiss = false() and ForeignElem($elem/position_parent_id)/is_disbanded = false() return $elem

IsHierChild / Hier

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

Например, найдём все вложенные подразделения для родительского подразделения:

for $elem in subdivisions where IsHierChild($elem/id, 6327975429225669221) order by $elem/Hier() return $elem/id

Конструкция order by $elem/Hier(), в данном случае, является обязательной

MatchSome

Функция предназначена для поиска по массиву значений.

Например, нам необходимо найти все мероприятия с типом Разовое мероприятие и Вебинар, для этого мы воспользуемся сравнением со списком наших значений:

for $elem in events where MatchSome($elem/type_id, ('one_time', 'webinar')) return $elem

Данную функцию так же можно использовать для исключения:

for $elem in events where MatchSome($elem/type_id, ('one_time', 'webinar')) = false() return $elem

Some / Satisfies

Функция позволяет выполнять запрос по двум таблицам, в какой-то степени является аналогом join в SQL.

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

В примере ниже представлен запрос для выборки назначенных пользователю квалификаций, имеющих статус active.

for $elem in qualification_assignments where $elem/person_id =
6148914691236517121 and some $qual in qualifications satisfies ($qual/status="active" and $qual/id = $elem
/qualification_id) return $elem

Оптимизация запросов

Универсальность - это хорошо, но не всегда выходит получить решение, удовлетворяющее нас в плане скорости его работы, поэтому, если вы понимаете, что какой-то запрос проще написать с использованием SQL - лучше использовать его. Но, помните, что данный подходит может потребовать от вас переписать все запросы на другой диалект, в случае миграции на другую базу данных. Если же вы остаётесь на стороне XQuery, вашему вниманию несколько способов для оптимизации запросов.

Не пренебрегайте использованием Fields

Банально, но, в большинстве случаев, вам нужно лишь несколько столбцов из выборки - так зачем вытаскивать их все?

Пример:

for $elem in collaborators where $elem/is_dismiss = false() return $elem/Fields("id")

Не забывайте про $elem/__data

Если логика вашего программного кода выглядит таким образом, что после выборки вы сразу же вызываете в цикле множество OpenDoc(), используйте конструкцию return $elem/id, $elem/__data - это позволит оптимизировать последующие открытия документов.

Пример:

for $elem in documents where contains($elem/code, "faq_") return $elem/id, $elem/__data

Используйте $elem_qc в MatchSome

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

Пример:

for $elem_qc in collaborators where MatchSome($elem_qc/position_parent_id, (6327975429225669221, 7059754636873218982)) return $elem_qc/Fields("id")

Финал

Надеюсь, вы узнали для себя что-то новое и у вас получится применять данные приёмы в работе - если же вы знаете о какой-то функциональности, не упомянутой в статье (например join, который не так давно добавили) - пиши об этом в комментариях.

И всегда помните, что это не тот XQuery, что используется в T-SQL.

FwklQIeMu0S4RPBwDM99rOqKZLqgeXvhmIAzQw7CXavp8D7Rnvxo7CmJ69MY1r0tOx2dSiuiFgkrI1IgikloefDHaI8h3glYV99h31nGF82EM9mZMaSkog5FkPxuv7oQ.jpeg
Оценка:
Eugene Chichilenko
Eugene Chichilenko20 мар. 2026 г., 19:20
Важно ещё отметить, что может быть указан запрос в xquery, но он не будет вливать на всех платформах, если вы используете конструкции, не заявленные в xquery. $elem/id in(1,2,3) будет работать с SQL базой, но не будет работать в XML. В данном случае правильно использовать matchsome, но иногда об этом забывают
Чтобы оставить комментарий, необходимо войти в систему