Блог Горошко Андрея 1C-Битрикс Использование Bitrix\Main\ORM\Query\Query для построения сложных запросов к Highload-блокам

Использование Bitrix\Main\ORM\Query\Query для построения сложных запросов к Highload-блокам

Средний рейтинг
Еще нет оценок

Highload-блоки в Битрикс — это эффективный инструмент для работы с крупными объемами данных, значительно превосходящий стандартные инфоблоки по производительности, особенно в условиях высоких нагрузок. Они оптимизированы для хранения и обработки больших объемов информации, используя подход, схожий с NoSQL-хранилищами. Взаимодействие с данными Highload-блоков осуществляется через объектно-ориентированные модели (ORM), что позволяет выполнять операции создания, чтения, обновления и удаления (CRUD) с помощью объектных методов.

Класс Bitrix\Main\ORM\Query\Query в рамках ORM Битрикс D7 предоставляет мощные возможности для построения сложных запросов к данным, включая Highload-блоки, обеспечивая гибкость и контроль над формированием SQL-запросов.

Для построения сложных запросов к Highload-блокам с использованием Bitrix\Main\ORM\Query\Query необходимо выполнить несколько ключевых шагов.

1. Подключение модуля Highload-блоков

Перед началом работы с Highload-блоками через D7 API обязательно подключите модуль highloadblock.

<?php
use Bitrix\Main\Loader;
use Bitrix\Highloadblock as HL;
use Bitrix\Main\Entity;
use Bitrix\Main\ORM\Query\Query;

Loader::includeModule("highloadblock");
?>

2. Получение сущности Highload-блока

Каждый Highload-блок представляет собой уникальную сущность, с которой работает ORM. Для получения этой сущности требуется знать ID или название Highload-блока.

<?php
$hlBlockId = 1; // Замените на ID вашего Highload-блока
$hlblock = HL\HighloadBlockTable::getById($hlBlockId)->fetch();

if (!$hlblock) {
    throw new \Exception("Highload-блок с ID " . $hlBlockId . " не найден.");
}

$entity = HL\HighloadBlockTable::compileEntity($hlblock);
$dataClass = $entity->getDataClass();
?>

3. Создание объекта Query и построение запроса

После получения класса DataManager для Highload-блока можно приступать к формированию запросов. Несмотря на то, что метод getList() широко используется, Bitrix\Main\ORM\Query\Query предоставляет более широкие возможности для конструирования сложных запросов.

Примеры построения сложных запросов:

Выборка с фильтрацией, сортировкой и ограничением

Методы setSelect() для указания выбираемых полей, setFilter() для фильтрации данных, setOrder() для сортировки и setLimit() для ограничения количества записей являются основными при работе с классом Query.

<?php
$query = new Query($entity);
$query->setSelect(['ID', 'UF_NAME', 'UF_VALUE']); // Выбираем поля ID, UF_NAME, UF_VALUE
$query->setFilter([
    '=UF_CATEGORY' => 10, // Фильтр по UF_CATEGORY, равный 10
    '>UF_PRICE' => 1000  // Фильтр по UF_PRICE, больше 1000
]);
$query->setOrder(['UF_NAME' => 'ASC']); // Сортировка по UF_NAME по возрастанию
$query->setLimit(10); // Ограничение на 10 записей

$result = $query->exec();
while ($row = $result->fetch()) {
    print_r($row);
}
?>

Использование логических операторов в фильтре

Условия в фильтре можно комбинировать с помощью логического оператора LOGIC (OR или AND).

<?php
$query = new Query($entity);
$query->setSelect(['ID', 'UF_PRODUCT_NAME']);
$query->setFilter([
    'LOGIC' => 'OR',
    ['=UF_STATUS' => 'active'],
    ['=UF_STATUS' => 'pending', '>UF_DATE_CREATED' => '2025-01-01']
]);
$result = $query->exec();
while ($row = $result->fetch()) {
    print_r($row);
}
?>

Объединение таблиц (JOIN)

Для связывания Highload-блоков с другими сущностями (например, инфоблоками или другими Highload-блоками) используется динамическая регистрация полей через registerRuntimeField с типом ReferenceField. Класс Bitrix\Main\ORM\Query\Join предоставляет методы для определения условий объединения, например, on().

<?php
use Bitrix\Main\Entity\ReferenceField;
use Bitrix\Iblock\ElementTable; // Пример для инфоблоков

$query = new Query($entity);
$query->setSelect([
    'ID',
    'UF_ELEMENT_ID',
    'ELEMENT_NAME' => 'ELEMENT.NAME', // Выбираем название элемента из связанной сущности
]);
$query->registerRuntimeField(
    'ELEMENT',
    new ReferenceField(
        'ELEMENT',
        ElementTable::class, // Класс сущности, с которой связываем
        ['=this.UF_ELEMENT_ID' => 'ref.ID'], // Условие связи (this - текущий HL-блок, ref - связанная сущность)
        ['join_type' => 'inner'] // Тип JOIN (inner, left, right)
    )
);
$query->setFilter(['=ELEMENT.IBLOCK_ID' => 5]); // Фильтр по ID инфоблока
$result = $query->exec();
while ($row = $result->fetch()) {
    print_r($row);
}
?>

Группировка и агрегатные функции

Возможность группировки данных с помощью setGroup() и выполнения агрегатных функций (таких как COUNTAVGSUMMAXMIN) через Entity\ExpressionField в setSelect() значительно расширяет функционал запросов.

<?php
$query = new Query($entity);
$query->setSelect([
    'UF_CATEGORY',
    new Entity\ExpressionField('COUNT_ITEMS', 'COUNT(%s)', 'ID'), // Подсчет элементов
    new Entity\ExpressionField('AVG_PRICE', 'AVG(%s)', 'UF_PRICE') // Средняя цена
]);
$query->setGroup(['UF_CATEGORY']);
$result = $query->exec();
while ($row = $result->fetch()) {
    print_r($row);
}
?>

Runtime-поля (runtime section) в Query или getList позволяют динамически регистрировать новые поля для конкретного запроса. Это могут быть ExpressionField для вычислений или поля других типов, что фактически расширяет карту сущности на время выполнения запроса и особенно полезно для объединения данных из различных Highload-блоков без изменения их оригинальных ORM-моделей.

Важные моменты и лучшие практики при работе с ORM и Highload-блоками

  • Явное указание полей: Всегда явно указывайте поля в setSelect(). Это позволяет избежать избыточной выборки данных, что положительно сказывается на производительности.
  • Использование операторов: Для точного соответствия используйте оператор =. Отсутствие явного оператора может привести к использованию LIKE Битриксом по умолчанию, что замедляет запросы.
  • Множественные поля: Работа с полями типа «множественное» требует особого внимания, так как они могут храниться в сериализованном виде или в отдельных таблицах. Учитывайте это при построении запросов.
  • Отслеживание запросов: Для отладки и оптимизации используйте Application::getConnection()->startTracker() и getTrackerQuery()->getSql() для просмотра сгенерированного SQL-запроса. Это помогает понять, какой именно SQL-запрос выполняется.
  • Производительность и кэширование: Хотя Highload-блоки созданы для высоких нагрузок, при очень больших объемах данных может потребоваться дополнительная оптимизация базы данных (индексация) и кэширование. ORM Битрикс поддерживает кэширование запросов с параметром ttl (time to live), включая запросы с JOIN’ами. Кэш автоматически сбрасывается при операциях addupdatedelete и может быть очищен вручную через cleanCache() для сущности.
  • Обработчики событий Highload-блоков: Highload-блоки поддерживают различные события (OnBeforeAddOnAfterAddOnBeforeUpdateOnAfterUpdateOnBeforeDeleteOnAfterDelete). Эти события позволяют внедрять пользовательскую логику до или после операций изменения данных, что дает возможности для валидации, модификации данных или выполнения дополнительных действий.
  • Структура класса Query: Класс Bitrix\Main\ORM\Query\Query содержит множество защищенных методов (buildSelect()buildJoin()buildWhere()buildGroup()buildHaving()buildOrder()), которые отвечают за построение соответствующих частей SQL-запроса, а также управляет внутренними цепочками для различных условий запроса. Понимание их предназначения может быть полезно для глубокой отладки.

Использование Bitrix\Main\ORM\Query\Query с Highload-блоками обеспечивает мощный и гибкий инструмент для работы с данными, позволяя эффективно строить даже самые сложные запросы.

Мой рейтинг:

Добавить комментарий

Related Post

Отправка Push-уведомлений с сервера: Модуль Pull and PushОтправка Push-уведомлений с сервера: Модуль Pull and Push

Средний рейтинг Еще нет оценок Модуль «Push & Pull» позволяет серверу отправлять данные в браузер пользователя без запроса со стороны клиента (без AJAX-опросов). Это основа чатов, уведомлений и обновлений канбана

Постраничная навигация в D7: Класс Bitrix\Main\UI\PageNavigationПостраничная навигация в D7: Класс Bitrix\Main\UI\PageNavigation

Средний рейтинг Еще нет оценок В старом ядре навигация была жестко привязана к объекту результата выборки (CDBResult). В D7 навигация — это отдельный, независимый объект, который «знает» о текущей странице

Консольные команды в Битрикс: Создание CLI-скриптов для bitrix.phpКонсольные команды в Битрикс: Создание CLI-скриптов для bitrix.php

Средний рейтинг Еще нет оценок В современном Битрикс (с версии main 20.100.0) появилась нативная поддержка консольных команд на базе Symfony Console. Теперь вместо создания разрозненных PHP-файлов для CRON можно писать структурированные