Поделиться через


Геопространствовые функции OData в поиске ИИ Azure и geo.distancegeo.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

Следующие шаги