Поля и объединение списков
Как извлечь вложенные поля ответа сервиса, рассчитать значение для каждой строки и соединить два списка по общему коду.
На этой странице
Сервис заказов вернул имя клиента внутри customer, а стоимость нужно посчитать из цены и количества. В другом списке лежат названия занятий, к которым относятся заказы. Эти данные можно подготовить двумя действиями:
- Преобразовать поля списка (
list_map) создаёт нужные поля у каждой строки. - Соединить списки (
list_join) добавляет данные из второго списка по совпадающему ключу.
Оба действия работают с уже загруженными данными. Они не запрашивают внешние сервисы и не изменяют записи коллекции. Для фильтрации, сортировки и подсчёта используйте другие действия над списками.
Получить имя и рассчитать стоимость
Допустим, предыдущий запрос сохранил под именем orders такой массив:
[
{"id":"o1","customer":{"name":"Анна"},"price":1500,"quantity":2},
{"id":"o2","price":2000,"quantity":1}
]
В Преобразовать поля списка выберите источник orders. Добавьте два поля результата:
| Новое поле | Операция | Откуда взять значение |
|---|---|---|
guest_name | Копировать | Путь customer.name; значение по умолчанию Без имени |
amount | Умножить | Пути price и quantity |
Сохраните результат под именем prepared_orders. Технические параметры:
{
"source": "orders",
"fields": [
{"as":"guest_name","op":"copy","path":"customer.name","default":"Без имени"},
{"as":"amount","op":"multiply","paths":["price","quantity"]}
],
"keep_fields": false,
"save_to_ctx": "prepared_orders"
}
В prepared_orders.rows ожидаются две строки:
[
{"guest_name":"Анна","amount":3000},
{"guest_name":"Без имени","amount":2000}
]
Если нужны также исходные id, price и quantity, включите сохранение остальных полей (keep_fields=true). Без этой настройки в обычной строке останутся только созданные поля. Служебные поля настоящего результата поиска сохраняются отдельно и не заменяются вашими вычислениями.
Доступные операции
| Операция | Параметр op | Пример применения |
|---|---|---|
| Копировать поле | copy | Взять customer.name |
| Задать значение | literal | Добавить source="catalog" каждой строке |
| Соединить текст | concat | Соединить несколько скалярных полей |
| Сложить | add | Сложить стоимость и доставку |
| Вычесть | subtract | Вычесть скидку |
| Умножить | multiply | Цена × количество |
| Разделить | divide | Сумма / число участников |
Для копирования укажите path, для нескольких операндов – paths, для постоянного значения – value. Каждый расчёт читает исходную строку. Поле, созданное выше в том же действии, не становится входом следующего поля: для такого расчёта добавьте ещё одно действие.
Арифметика выполняется в порядке перечисления операндов. Например, subtract с тремя путями означает «первое минус второе минус третье». Числа остаются точными: 0.1 × 3 даёт 0.3. Деление округляется до 12 знаков после запятой; деление на ноль и выход за числовые ограничения дают ошибку.
Необязательный type преобразует результат к text, number или boolean. Числовая строка "1500" может стать числом. Для логического преобразования подходят логическое значение либо строки "true" и "false". Неверные значения не превращаются незаметно в ноль или false.
Вложенные пути и пустые значения
Путь customer.name выбирает имя из объекта customer. Путь items.0.id выбирает ID первого элемента массива; отсчёт начинается с нуля.
Если в исходном объекте есть буквальный ключ с точкой, например "customer.name", используйте JSON Pointer /customer.name. В JSON Pointer символ / внутри ключа записывается как ~1, а ~ как ~0.
Значение по умолчанию применяется, когда поле отсутствует. Явное null считается присутствующим значением и не заменяется автоматически. Копирование отсутствующего поля без значения по умолчанию даёт null; числовая операция над отсутствующим, пустым или ошибочным числом завершается ошибкой.
Добавить к заявкам названия занятий
Пусть первый список bookings содержит заявки:
[
{"id":"b1","class_code":"wc","guest":"Анна"},
{"id":"b2","class_code":"clay","guest":"Борис"},
{"id":"b3","class_code":"photo","guest":"Вера"}
]
Во втором списке classes находятся занятия:
[
{"code":"wc","name":"Акварель"},
{"code":"clay","name":"Лепка"}
]
Добавьте Соединить списки: слева bookings, справа classes, ключи class_code и code. Оставьте левое объединение, политику неоднозначности «Ошибка» и префикс правых полей details_. Сохраните как joined_bookings.
{
"source": "bookings",
"right_source": "classes",
"left_key": "class_code",
"right_key": "code",
"mode": "left",
"multiple": "error",
"right_prefix": "details_",
"save_to_ctx": "joined_bookings"
}
В результате первая строка содержит guest="Анна" и details_name="Акварель", вторая – guest="Борис" и details_name="Лепка". Заявка Веры остаётся без добавленных полей: занятия photo во втором списке нет.
Префикс защищает от одинаковых имён полей. Например, с префиксом class_ правое поле code получило бы имя class_code, которое уже есть слева. Действие сообщит о конфликте, поэтому выберите другой префикс, как details_ в примере.
Служебные поля _record_id, _score и _match_type правого результата не добавляются: строка результата по-прежнему относится к левой записи. Если нужен ID правой записи, перед объединением скопируйте её _record_id действием Преобразовать поля списка в обычное поле, например class_record_id. После объединения оно будет доступно с выбранным префиксом, например details_class_record_id.
Что делать с отсутствующими и повторяющимися ключами
| Настройка | Поведение |
|---|---|
Левое объединение (mode=left) | Оставляет все строки первого списка, даже без совпадения |
Только совпадения (mode=inner) | Оставляет строки, для которых нашлась запись справа |
Ошибка при нескольких совпадениях (multiple=error) | Не выбирает неоднозначную запись молча |
Первое совпадение (multiple=first) | Берёт первую подходящую строку правого списка |
Все совпадения (multiple=all) | Создаёт отдельную строку для каждого совпадения |
В режиме all число строк может вырасти. Например, две заявки и три записи справочника с одним кодом дадут шесть строк. Такой результат подчиняется общим ограничениям объёма.
Отсутствующие ключи и значения null не совпадают друг с другом. Пустая строка "" считается обычным текстовым ключом и может совпасть с другой пустой строкой; если это нежелательно, заранее отфильтруйте такие строки. Тип ключа тоже важен: число 1 отличается от строки "1". Объекты и массивы не подходят как ключи соединения. Числовые значения сравниваются точно, без потери больших ID; идентификаторы сервисов обычно удобнее хранить строками.
Порядок первого списка сохраняется. Если выбраны все совпадения, строки второго списка добавляются в их исходном порядке. Поэтому «Первое совпадение» имеет смысл только тогда, когда вы заранее знаете порядок правого списка.
Полнота, ограничения и проверка
На каждый вход и результат действует предел 10 000 строк. Для объединения размер двух входов вместе ограничен 16 МиБ; выход также ограничен по размеру. Допустимо до 256 настроек полей. Превышение вызывает ошибку, а не скрытое удаление лишних строк.
Дополнительно ограничена вычислительная работа: не больше 1 000 000 условных операций на действие. Учитываются строки, количество настраиваемых полей, операнды и глубина путей; для объединения также учитывается число создаваемых строк и полей. Если преобразование слишком сложное, сократите входной список, ненужные поля или число операндов. Ограничение проверяется до большого расчёта. Проверка также прекращается при отмене запроса.
В предел 16 МиБ результата входит небольшой резерв 512 байт для служебных полей. Поэтому строка, занимающая почти весь предел, может не поместиться вместе с результатом операции. Большие промежуточные строки и неоднозначное размножение результатов ограничиваются до их накопления в памяти.
Если любой исходный результат был неполным, объединённый результат остаётся неполным. Действие не может узнать о совпадении, которое не было загружено из правого источника. Не показывайте отсутствие совпадения как доказательство отсутствия записи во всей базе.
Предварительная проверка принимает буквальные JSON-данные. Она не запускает реакцию, не вызывает внешние сервисы и не записывает изменения в коллекции. Для всей несохранённой цепочки используйте проверку черновика на учебных данных: получение данных → преобразование → подготовка кнопки или сообщения. После сохранения отдельно проверьте путь через подключённого бота и канал. Этот запуск выполняет сохранённые действия, включая обращения к сервисам и изменения записей.
Для ручной проверки используйте четыре случая: обычная строка, отсутствующее вложенное поле, повтор ключа справочника и неполный исходный список. В результате проверьте порядок, количество строк и признак полноты.
Связанные материалы: свойства списков и итоги, коллекции, практика работы с каталогом.