При работе с интерфейсом OData в системе 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда стандартные фильтры по идентификаторам не возвращают данные, хотя объекты гарантированно существуют в базе. Особенно остро эта проблема проявляется при попытке выполнить отбор по полю Owner (Владелец) в подчиненных справочниках, таких как Характеристики номенклатуры. Разберем подробно, почему это происходит и как составить корректный запрос.
Рассмотрим стандартную ситуацию: нам необходимо получить все характеристики для конкретной номенклатуры, зная ее GUID. Мы анализируем метаданные ($metadata) и видим следующую структуру для сущности Catalog_ХарактеристикиНоменклатуры:
<Property Name="Owner" Type="Edm.String" Nullable="true"/>
<Property Name="Description" Type="Edm.String" Nullable="true"/>
<Property Name="Owner_Type" Type="Edm.String" Nullable="true"/>
На первый взгляд, поле Owner является обычной строкой. Мы логично предполагаем, что обычный фильтр по строковому представлению GUID должен сработать. Однако запрос вида $filter=Owner eq 'ae8d0dac-5a7c-11ed-88ce-d8bbc189bb8e' возвращает пустой массив value: []. При этом аналогичный фильтр по полю Description отрабатывает корректно. Проанализируем ситуацию: почему два поля с одинаковым типом Edm.String ведут себя по-разному?
Выясним причину такого поведения. В платформе 1С поле Владелец почти всегда является составным типом данных. Даже если в конфигураторе в качестве владельца указан только один справочник, системно 1С закладывает возможность расширения. В протоколе OData 3.0, который используется в 1С, нет нативного типа для передачи "произвольной ссылки". Поэтому платформа маскирует такие поля под Edm.String.
Важный технический нюанс: в базе данных 1С ссылки хранятся в бинарном 16-байтовом формате. Когда мы отправляем запрос с фильтром eq 'строка', система пытается выполнить прямое текстовое сравнение в SQL-запросе. Но в колонке владельца хранятся не строки, а двоичные данные (ссылки). Поскольку типы не совпадают на уровне движка базы данных, 1С не может сопоставить ваш текстовый GUID с бинарным идентификатором, и результат оказывается пустым.
Если же мы попробуем использовать литерал guid'...' напрямую (например, $filter=Owner eq guid'...'), то получим ошибку совместимости типов:
"Неверные параметры в операции сравнения. Нельзя сравнивать поля неограниченной длины и поля несовместимых типов."
Это происходит потому, что метаданные жестко задекларировали Owner как Edm.String, и OData-протокол запрещает сравнивать строку с типом Guid напрямую.
Единственным правильным способом выполнения отбора по ссылочным полям, которые в метаданных помечены как строки, является использование функции cast(). В контексте 1С OData эта функция работает не просто как приведение типов, а как конструктор объекта "Ссылка".
Проанализируем синтаксис правильного запроса:
https://server/db/odata/standard.odata/Catalog_ХарактеристикиНоменклатуры?$filter=Owner eq cast(guid'ae8d0dac-5a7c-11ed-88ce-d8bbc189bb8e', 'Catalog_Номенклатура')
Разберем по шагам, что происходит в этом запросе:
guid'...', чтобы система понимала, что это уникальный идентификатор, а не просто набор символов.cast(), где вторым параметром указываем имя сущности в формате 1С OData (например, 'Catalog_Номенклатура').После такой манипуляции запрос начнет возвращать корректные данные, так как сравнение в SQL-запросе будет происходить между двумя бинарными ссылками одного типа.
Если использование функции cast() кажется вам громоздким, рассмотрим другой способ, который часто применяется в разработке. Если в вашей версии платформы и конфигурации для поля Owner создано навигационное свойство (Navigation Property), вы можете обратиться к его внутреннему ключу Ref_Key, который всегда имеет тип Edm.Guid.
Посмотрим на пример такого запроса:
$filter=Owner/Ref_Key eq guid'ae8d0dac-5a7c-11ed-88ce-d8bbc189bb8e'
Преимущества этого метода:
Ref_Key — это всегда Edm.Guid.В некоторых случаях эффективнее запрашивать не характеристики с фильтром по владельцу, а саму номенклатуру, "разворачивая" связанные данные. Это позволяет получить объект владельца и все его характеристики одним пакетом.
Рассмотрим пример запроса:
https://server/db/odata/standard.odata/Catalog_Номенклатура(guid'ae8d0dac-5a7c-11ed-88ce-d8bbc189bb8e')?$expand=Характеристики
В этом случае 1С сама разрешит все связи на уровне метаданных. Однако помните, что для работы этого метода в конфигурации 1С должно быть настроено использование соответствующих связей в составе ODATA (состав стандартного интерфейса).
Подведем итоги нашего анализа. Столкнувшись с пустым результатом при фильтрации в 1С OData, выполните следующие действия:
$metadata. Если это Edm.String, но поле ссылается на объект (как Owner), обычное текстовое сравнение eq '...' не сработает.cast(guid'UUID', 'Target_Type') для корректного преобразования._Type в метаданных. Наличие поля Owner_Type — явный признак того, что основное поле требует особого обращения через cast.Catalog_ вместо Справочник.).Использование функции cast() — это не просто "хак", а штатный механизм платформы для работы с полиморфными (составными) типами данных в условиях ограничений протокола OData 3.0. Понимание этого механизма позволит вам строить надежные интеграции с системой 1С.