Как правильно наложить фильтр в 1С OData при поиске объекта по GUID?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет IT и автоматизация бизнеса
← На главную

При работе с REST-интерфейсом (OData) в 1С программисты часто сталкиваются с ситуацией, когда необходимо получить данные конкретного объекта, но при этом наложить на него дополнительные условия. Типичный пример: у нас есть GUID договора, и нам нужно проверить, заполнена ли в нем организация или не равна ли нулю сумма, и сделать это в рамках одного запроса.

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

Причина игнорирования фильтра при обращении по GUID

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

.../odata/standard.odata/Catalog_ДоговорыКонтрагентов(guid'59873b45-91a3-11e9-8db6-f38a2508e13e')?$filter=Сумма ne 0

Мы увидим, что 1С возвращает весь объект договора целиком, даже если условие Сумма ne 0 не выполняется. Это происходит потому, что согласно спецификации OData, когда идентификатор (ключ) указан в скобках сразу после имени сущности, система обращается к конкретному ресурсу типа Entity. В реализации 1С механизм $filter предназначен для работы с наборами сущностей (Collection). Если объект уже идентифицирован по GUID в адресе, движок OData считает поиск завершенным и просто отдает данные объекта, игнорируя параметры фильтрации.

Решение проблемы: переход к фильтрации коллекции

Чтобы заставить систему учитывать дополнительные условия, мы должны обратиться не к конкретному объекту, а к коллекции (справочнику в целом), и уже в параметре $filter указать и GUID самого объекта, и дополнительные критерии. Рассмотрим, как должен выглядеть правильный запрос:


.../odata/standard.odata/Catalog_ДоговорыКонтрагентов?$filter=Ref_Key eq guid'59873b45-91a3-11e9-8db6-f38a2508e13e' and Сумма ne 0

В этом случае, если условие не будет выполнено (например, сумма равна нулю), сервер вернет пустой массив value, что и требуется для логической проверки в коде вызывающей системы:


{
    "odata.metadata": "...",
    "value": []
}

Использование суффикса _Key и функции cast

Выясним важный нюанс при работе со ссылочными полями. В 1С OData для ссылок (организации, контрагенты, склады) существуют виртуальные поля с суффиксом _Key. Если нам нужно проверить, заполнена ли организация (сравнить с пустой ссылкой), нам необходимо использовать функцию cast, особенно если реквизит имеет составной тип данных. Без cast система может выдать ошибку о несовместимости типов.

Посмотрим на пример запроса, который проверяет, что в конкретном договоре организация заполнена (не равна пустой ссылке):


.../odata/standard.odata/Catalog_ДоговорыКонтрагентов?$filter=Ref_Key eq guid'59873b45-91a3-11e9-8db6-f38a2508e13e' and cast(Организация_Key, 'Catalog_Организации') ne guid'00000000-0000-0000-0000-000000000000'

Важные моменты:

  1. Для уникального идентификатора самого объекта используем системное поле Ref_Key.
  2. Для реквизитов объекта используем их имена с суффиксом _Key (например, Организация_Key).
  3. Пустая ссылка в 1С всегда представлена как guid'00000000-0000-0000-0000-000000000000'.

Оптимизация запроса через $select

Когда нашей целью является только проверка состояния поля, получать весь объект договора (который может быть очень "тяжелым" из-за табличных частей или длинных строк) неэффективно. Разберем, как ограничить набор возвращаемых данных с помощью $select.

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


.../odata/standard.odata/Catalog_ДоговорыКонтрагентов?$filter=Ref_Key eq guid'...' and Сумма gt 100&$select=Ref_Key

Это значительно снизит нагрузку на сеть и ускорит сериализацию данных на стороне сервера 1С.

Работа с табличными частями и дополнительными реквизитами

Рассмотрим более сложный случай, когда нужно отфильтровать объект по значению в его табличной части, например, по значению Дополнительного реквизита. Для этого используется оператор any, который проверяет наличие хотя бы одной строки, соответствующей условию.

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


.../odata/standard.odata/Catalog_Номенклатура?$select=Ref_Key,Description,ДополнительныеРеквизиты/Значение&$filter=ДополнительныеРеквизиты/any(d: cast(d/Значение, 'Catalog_ЗначенияСвойствОбъектов') eq guid'9ea85d06-3828-11ea-bb92-0050560102b0')

В данном примере мы анализируем коллекцию ДополнительныеРеквизиты. С помощью d: мы вводим алиас для строки табличной части и применяем к полю Значение функцию cast, чтобы сравнить его с конкретным GUID значения свойства. Это мощный инструмент, позволяющий строить сложные выборки через REST без написания дополнительного кода в самой конфигурации 1С.

Подведение итогов

Проанализировав особенности работы OData в 1С, мы можем сформулировать золотое правило: никогда не используйте фильтр при обращении к объекту через скобки. Всегда используйте обращение к коллекции с фильтрацией по Ref_Key.

Основные инструменты для построения корректных запросов:

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

← На главную