Геопространствовые функции OData в поиске ИИ Azure и geo.distance
geo.intersects
Поиск ИИ Azure поддерживает геопространствованные запросы в выражениях фильтров OData с помощью geo.distance
функций и geo.intersects
функций. Функция geo.distance
возвращает расстояния в километрах между двумя точками, одна из которых представляет собой поле или переменную диапазона, а другая — константу, переданную как часть фильтра. Функция geo.intersects
возвращает значение true
, если заданная точка находится в пределах указанного многоугольника, где точка представляет собой поле или переменную диапазона, а многоугольник указывается в качестве константы, переданной как часть фильтра.
Функцию geo.distance
также можно использовать в параметре $orderby для сортировки результатов поиска по расстоянию от заданной точки. Синтаксис для geo.distance
в $orderby такой же, как и в $filter. При использовании функции geo.distance
в $orderby поле, к которому она применяется, должно быть сортируемым и принадлежать к типу Edm.GeographyPoint
.
Примечание.
При использовании geo.distance
в параметре $orderby поле, передаваемое в функцию, должно содержать только одну географическую точку. Иными словами, оно должно принадлежать к типу Edm.GeographyPoint
, а не Collection(Edm.GeographyPoint)
. Невозможно сортировать поля коллекции в службе "Поиск ИИ Azure".
Синтаксис
Следующая EBNF (Расширенная форма Бэкуса-Наура) определяет грамматику функций geo.distance
и geo.intersects
, а также геопространственные значения, с которыми они работают.
geo_distance_call ::=
'geo.distance(' variable ',' geo_point ')'
| 'geo.distance(' geo_point ',' variable ')'
geo_point ::= "geography'POINT(" lon_lat ")'"
lon_lat ::= float_literal ' ' float_literal
geo_intersects_call ::=
'geo.intersects(' variable ',' geo_polygon ')'
/* You need at least four points to form a polygon, where the first and
last points are the same. */
geo_polygon ::=
"geography'POLYGON((" lon_lat ',' lon_lat ',' lon_lat ',' lon_lat_list "))'"
lon_lat_list ::= lon_lat(',' lon_lat)*
Кроме того, вам может помочь интерактивная схема синтаксиса:
Примечание.
См . справочник по синтаксису выражений OData для поиска ИИ Azure для полного EBNF.
geo.distance
Функция geo.distance
принимает два параметра типа Edm.GeographyPoint
и возвращает значение Edm.Double
, которое представляет собой расстояние между ними в километрах. В отличие от нее другие службы, которые поддерживают геопространственные операции OData, обычно возвращают расстояние в метрах.
Один из параметров geo.distance
должен быть константой географической точки, а другой — путем к полю (или переменной диапазона в случае итерации с использованием фильтра по полю типа Collection(Edm.GeographyPoint)
). Порядок этих параметров не имеет значения.
Константа географической точки имеет форму geography'POINT(<longitude> <latitude>)'
, где долгота и широта являются числовыми константами.
Примечание.
При использовании функции geo.distance
в фильтре необходимо сравнить возвращаемое ей расстояние с константой с помощью операторов lt
, le
, gt
или ge
. Операторы eq
и ne
не предназначены для сравнения расстояний. В следующем примере показано правильное использование функции geo.distance
: $filter=geo.distance(location, geography'POINT(-122.131577 47.678581)') le 5
.
geo.intersects
Функция geo.intersects
принимает переменную типа Edm.GeographyPoint
и константу Edm.GeographyPolygon
и возвращает Edm.Boolean
-- true
, если точка находится внутри границ многоугольника. В противном случае возвращается значение false
.
Многоугольник — это двумерная поверхность, которая хранится в виде последовательности точек, определяющих ограничивающее кольцо (см. примеры ниже). Многоугольник должен быть замкнут, то есть первая и конечная точки должны совпадать. Точки многоугольника должны наноситься в порядке против часовой стрелки.
Геопространственные запросы и многоугольники, охватывающие 180-й меридиан
Для многих библиотек геопространственных запросов формирование запроса, включающего 180-й меридиан (около линии перемены даты), либо запрещено, либо требует обходного пути, такого как разделение многоугольника на два, по одному с каждой стороны меридиана.
В поиске ИИ Azure геопространствированные запросы, включающие 180-градусную долготу, будут работать должным образом, если фигура запроса прямоугольна, а координаты выравниваются по макету сетки вдоль долготы и широты (например, geo.intersects(location, geography'POLYGON((179 65, 179 66, -179 66, -179 65, 179 65))'
). В противном случае для непрямоугольных или невыровненных фигур используйте подход с разделенным многоугольником.
Геопространственные функции и null
Как и все другие поля, отличные от коллекции в службе "Поиск ИИ Azure", поля типа Edm.GeographyPoint
могут содержать null
значения. Если поиск ИИ Azure вычисляет geo.intersects
поле, то null
результат всегда будет.false
Поведение geo.distance
в этом случае зависит от контекста:
- В фильтрах функция
geo.distance
для поляnull
в результате дастnull
. Это означает, что документ не будет соответствовать запросу, так как результатом вычисления при сравненииnull
с любым значением, отличным от NULL, будетfalse
. - При сортировке результатов с помощью $orderby результатом вычисления функции
geo.distance
для поляnull
будет максимально возможное расстояние. Документы с таким полем при сортировке будут располагаться ниже всех прочих, если направление сортировки —asc
(по умолчанию), и выше всех остальных, если направление —desc
.
Примеры
Примеры выражений фильтрации
Найти все отели в пределах 10 километров от заданного ориентира (где location — это поле типа Edm.GeographyPoint
):
geo.distance(location, geography'POINT(-122.131577 47.678581)') le 10
Найти все отели в заданном окне просмотра, описанном как многоугольник (где location — это поле типа Edm.GeographyPoint
). Обратите внимание, что многоугольник замкнут (первая и последняя точки должны совпадать, и точки должны быть нанесены в порядке против часовой стрелки).
geo.intersects(location, geography'POLYGON((-122.031577 47.578581, -122.031577 47.678581, -122.131577 47.678581, -122.031577 47.578581))')
Примеры выражений упорядочивания
Сортировать отели по убыванию параметра rating
, а затем по возрастанию расстояния от заданных координат:
rating desc,geo.distance(location, geography'POINT(-122.131577 47.678581)') asc
Сортировка отелей в порядке убывания по параметрам search.score
и rating
, а затем в порядке возрастания расстояния от заданных координат так, чтобы между двумя отелями с одинаковым рейтингом сначала отображался ближайший:
search.score() desc,rating desc,geo.distance(location, geography'POINT(-122.131577 47.678581)') asc