При работе с REST-интерфейсом (OData) в 1С программисты часто сталкиваются с ситуацией, когда необходимо получить данные конкретного объекта, но при этом наложить на него дополнительные условия. Типичный пример: у нас есть 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": []
}
Выясним важный нюанс при работе со ссылочными полями. В 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'
Важные моменты:
Ref_Key._Key (например, Организация_Key).guid'00000000-0000-0000-0000-000000000000'.Когда нашей целью является только проверка состояния поля, получать весь объект договора (который может быть очень "тяжелым" из-за табличных частей или длинных строк) неэффективно. Разберем, как ограничить набор возвращаемых данных с помощью $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.
Основные инструменты для построения корректных запросов:
Ref_Key — для идентификации объекта по его ссылке.cast(Поле, 'Тип') — для корректного сравнения ссылочных и составных типов.$select — для минимизации объема передаваемых данных.any / all — для фильтрации по табличным частям.Соблюдение этих правил позволит вам избежать странного поведения интерфейса, когда фильтры игнорируются, а результаты запросов кажутся случайными из-за изменения порядка полей в JSON-ответе.