Общие сведения о языке OData для $filter, $orderby и $select в службе Когнитивного поиска Azure

В этой статье представлен обзор языка выражений OData, используемого в выражениях $filter, $order и $select выражениях в Когнитивный поиск Azure. Язык представлен "снизу вверх", начиная с самых основных элементов. Выражения OData, которые можно создать в запросе, варьируются от простых до очень сложных, но все они имеют общие элементы. Общие элементы включают:

  • Пути к полям, которые ссылаются на определенные поля индекса.
  • Константы, являющиеся прямыми значениями определенного типа данных.

Разобравшись с этими общими понятиями, можно перейти к синтаксису верхнего уровня для каждого выражения:

  • $filter выражения вычисляются во время синтаксического анализа запроса, при этом поиск ограничивается определенными полями или добавляются критерии соответствия, используемые во время сканирования индекса.
  • $orderby выражения применяются в качестве шага постобработки над результирующим набором для сортировки возвращаемых документов.
  • $select выражения определяют, какие поля документа включены в результирующий набор.

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

Примечание

Терминология в Когнитивном поиске Azure отличается от стандарта OData в нескольких моментах. Поле Когнитивного поиске называется свойством в OData; аналогичным образом соответствуют друг другу понятия путь поля и путь к свойству. Индекс, содержащий документы в Когнитивном поиске Azure, обычно упоминается в OData как набор сущностей, содержащий сущности. Терминология Когнитивного поиск используется по всей этой статье.

Пути к полям

Следующая EBNF (Расширенная форма Бэкуса — Наура) определяет грамматику путей к полям.

field_path ::= identifier('/'identifier)*

identifier ::= [a-zA-Z_][a-zA-Z_0-9]*

Кроме того, доступна интерактивная схема синтаксиса:

Путь к полю состоит из одного или нескольких идентификаторов, разделенных косыми чертами. Каждый идентификатор представляет собой последовательность символов, которая должна начинаться с буквы ASCII или знака подчеркивания и содержать только буквы ASCII, цифры и символы подчеркивания. Буквы могут быть в верхнем или нижнем регистре.

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

Примеры путей к полям приведены в следующей таблице.

Путь к полю Описание
HotelName Ссылается на поле индекса верхнего уровня
Address/City Ссылается на подполе City сложного поля в индексе; Address в этом примере относится к типу Edm.ComplexType
Rooms/Type Ссылается на Type подполе сложного поля коллекции в индексе; Rooms в этом примере относится к типу Collection(Edm.ComplexType)
Stores/Address/Country Ссылается на Country подполе Address подполя сложного поля коллекции в индексе; Stores имеет тип Collection(Edm.ComplexType) и Address имеет тип Edm.ComplexType в этом примере.
room/Type Ссылается на подполе Type переменной room диапазона, например в выражении фильтра. Rooms/any(room: room/Type eq 'deluxe')
store/Address/Country Ссылается на подполе Country подполя Address переменной store диапазона, например в выражении фильтра. Stores/any(store: store/Address/Country eq 'Canada')

Значение пути к полю различается в зависимости от контекста. В фильтрах путь к полю означает значение одного экземпляра поля в текущем документе. В других контекстах, таких как $OrderBy, $selectили в поле поиска в полном синтаксисе Lucene, "путь к полю" означает само поле. Это различие влияет на использование путей к полям в фильтрах.

Пример: путь к полю Address/City. В фильтре это относится к одному городу для текущего документа, например "Сан-Франциско". В отличие от этого, Rooms/Type относится к подполю Type для многих комнат (например, "стандартный" для первого номера, "люкс" для второго номера и т. д.). Так как Rooms/Type не ссылается на один экземпляр подполя Type, его нельзя использовать непосредственно в фильтре. Вместо этого для фильтрации по типу комнаты можно использовать лямбда-выражение с переменной диапазона, например:

Rooms/any(room: room/Type eq 'deluxe')

В этом примере переменная диапазона room отображается в пути к полю room/Type. Таким образом, room/Type ссылается на тип текущей комнаты в текущем документе. Это один экземпляр подполя Type , поэтому его можно использовать непосредственно в фильтре.

Использование путей к полям

Пути к полям используются во многих параметрах интерфейсов REST API службы Когнитивного поиска Azure. В следующей таблице перечислены все места, где их можно использовать, а также все ограничения на их использование.

API Имя параметра Ограничения
Создание или Обновление индекса suggesters/sourceFields Нет
Создание или Обновление индекса scoringProfiles/text/weights Может ссылаться только на поля с возможностью поиска
Создание или Обновление индекса scoringProfiles/functions/fieldName Может ссылаться только на фильтруемые поля
Поиск search когда queryType имеет значение full Может ссылаться только на поля с возможностью поиска
Поиск facet Может ссылаться только на поля с аспектами
Поиск highlight Может ссылаться только на поля с возможностью поиска
Поиск searchFields Может ссылаться только на поля с возможностью поиска
Предложение и Автозаполнение searchFields Может ссылаться только на поля, являющиеся частью средства подбора
Поиск, Предложение и Автозаполнение $filter Может ссылаться только на фильтруемые поля
Поиск и Предложение $orderby Может ссылаться только на поля, доступные для сортировки
Поиск, Предложениеи Просмотр $select Может ссылаться только на извлекаемые поля

Константы

Константы в OData — это прямые значения заданного типа Модели данных сущности (EDM). Список поддерживаемых в службе Когнитивного поиска типов см. в разделе Поддерживаемые типы данных. Константы типов коллекций не поддерживаются.

В следующей таблице приведены примеры констант для каждого из типов данных, поддерживаемых Когнитивным поиском Azure.

Тип данных Примеры констант
Edm.Boolean true, false
Edm.DateTimeOffset 2019-05-06T12:30:05.451Z
Edm.Double 3.14159, -1.2e7, NaN, INF, -INF
Edm.GeographyPoint geography'POINT(-122.131577 47.678581)'
Edm.GeographyPolygon geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))'
Edm.Int32 123, -456
Edm.Int64 283032927235
Edm.String 'hello'

Исключение специальных символов в строковых константах

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

Например, фраза без форматированного апострофа, такая как "Alice's car" ("автомобиль Алисы"), будет представлена в OData в качестве строковой константы 'Alice''s car'.

Важно!

При создании фильтров программным способом важно помнить о необходимости исключать строковые константы, которые поступают из вводимых пользователем данных. Это позволяет снизить вероятность атак путем внедрения, особенно при использовании фильтров для реализации фильтрации по ролям безопасности.

Синтаксис констант

Следующая EBNF (Расширенная форма Бэкуса — Наура) определяет грамматику для большинства констант, показанных в приведенной выше таблице. Грамматику для геопространственных типов можно найти в статье Геопространственные функции OData в Когнитивном поиске Azure.

constant ::=
    string_literal
    | date_time_offset_literal
    | integer_literal
    | float_literal
    | boolean_literal
    | 'null'

string_literal ::= "'"([^'] | "''")*"'"

date_time_offset_literal ::= date_part'T'time_part time_zone

date_part ::= year'-'month'-'day

time_part ::= hour':'minute(':'second('.'fractional_seconds)?)?

zero_to_fifty_nine ::= [0-5]digit

digit ::= [0-9]

year ::= digit digit digit digit

month ::= '0'[1-9] | '1'[0-2]

day ::= '0'[1-9] | [1-2]digit | '3'[0-1]

hour ::= [0-1]digit | '2'[0-3]

minute ::= zero_to_fifty_nine

second ::= zero_to_fifty_nine

fractional_seconds ::= integer_literal

time_zone ::= 'Z' | sign hour':'minute

sign ::= '+' | '-'

/* In practice integer literals are limited in length to the precision of
the corresponding EDM data type. */
integer_literal ::= digit+

float_literal ::=
    sign? whole_part fractional_part? exponent?
    | 'NaN'
    | '-INF'
    | 'INF'

whole_part ::= integer_literal

fractional_part ::= '.'integer_literal

exponent ::= 'e' sign? integer_literal

boolean_literal ::= 'true' | 'false'

Кроме того, доступна интерактивная схема синтаксиса:

Создание выражений из путей к полям и констант

Пути к полям и константы — это основная часть любого выражения OData, но они сами по себе уже являются полными выражениями. Фактически, параметр $select в Когнитивном поиске является разделенным запятыми списком путей к полям, а $orderby не намного сложнее, чем $select. Если у вас есть поле типа Edm.Boolean в индексе, можно даже написать фильтр, состоящий только из пути к этому полю. Константы true и false также являются допустимыми фильтрами.

Однако в большинстве случаев требуются более сложные выражения, ссылающиеся на более чем одно поле и одну константу. Эти выражения создаются различными способами в зависимости от параметра.

Следующая EBNF (Расширенная форма Бэкуса — Наура) определяет грамматику для параметров $Filter, $orderby и $select. Они основаны на более простых выражениях, которые ссылаются на пути к полям и константы:

filter_expression ::= boolean_expression

order_by_expression ::= order_by_clause(',' order_by_clause)*

select_expression ::= '*' | field_path(',' field_path)*

Кроме того, доступна интерактивная схема синтаксиса:

Дальнейшие действия

Параметры $orderby и $select являются разделенными запятыми списками более простых выражений. Параметр $filter является логическим выражением, состоящим из более простых вложенных выражений. Эти вложенные выражения объединяются с помощью логических операторов, таких как and, orи not, операторов сравнения, таких как eq, ltgt, и т. д., и операторов сбора, таких как any и all.

Параметры $filter, $orderbyи $select подробно рассматриваются в следующих статьях: