Гео поиск

Одна из главных особенностей Manticore Search — возможность комбинировать полнотекстовый поиск с геолокацией. Например, ритейлер может предложить поиск, где пользователь ищет товар, а набор результатов может указывать ближайший магазин, в котором этот товар есть в наличии, чтобы пользователь мог прийти в магазин и забрать его. Туристический сайт может предоставлять результаты на основе поиска, ограниченного определённой областью, и сортировать результаты по расстоянию от точки (например, «поиск музеев рядом с отелем»).

Для выполнения гео-поиска документ должен содержать пары координат широты/долготы. Координаты могут храниться как атрибуты с плавающей точкой. Если в документе несколько локаций, может быть удобно использовать JSON-атрибут для хранения пар координат.

table myrt
{
    ...
    rt_attr_float = lat
    rt_attr_float = lon
    ...
}

Координаты могут храниться в градусах или радианах.

Если для атрибутов широты и долготы сгенерированы вторичные индексы, они могут автоматически использоваться для ускорения гео-поисков, если оптимизатор на основе стоимости решит их применить.

Выполнение расчёта расстояния

Чтобы узнать расстояние между двумя точками, можно использовать функцию GEODIST(). GEODIST требует две пары координат в качестве первых четырёх параметров.

5-й параметр в упрощённом JSON-формате может настраивать определённые аспекты функции. По умолчанию GEODIST ожидает координаты в радианах, но можно добавить in=degrees, чтобы использовать градусы в качестве входных данных. Координаты, для которых выполняется вычисление гео-расстояния, должны иметь тот же тип (градусы или радианы), что и хранящиеся в таблице; в противном случае результаты будут некорректными.

Вычисленное расстояние по умолчанию в метрах, но с опцией out его можно преобразовать в километры, футы или мили. Наконец, по умолчанию используется метод расчёта под названием adaptive. Альтернативный метод на основе алгоритма haversine также доступен; однако он медленнее и менее точен.

Результат функции — расстояние — можно использовать в предложении ORDER BY для сортировки результатов:

SELECT *, GEODIST(40.7643929, -73.9997683, lat, lon, {in=degrees, out=miles}) AS distance FROM myindex WHERE MATCH('...') ORDER BY distance ASC, WEIGHT() DESC;

Или для ограничения результатов радиальной областью вокруг точки:

SELECT *,GEODIST(40.7643929, -73.9997683, lat,lon, {in=degrees, out=miles}) AS distance FROM myindex WHERE MATCH('...') AND distance <1000 ORDER BY WEIGHT(), DISTANCE ASC;

Поиск внутри многоугольников

Ещё одна функция гео-поиска — возможность определить, находится ли локация внутри заданной области. Специальная функция создаёт объект многоугольника, который затем используется другой функцией для проверки, содержатся ли координаты внутри этого многоугольника или нет.

Доступны две функции для создания многоугольника:

  • GEOPOLY2D() — создаёт многоугольник с учётом кривизны Земли
  • POLY2D() — создаёт простой многоугольник в плоском пространстве

POLY2D подходит для гео-поиска, когда стороны области короче 500 км (для многоугольников с 3-4 сторонами; для многоугольников с большим числом сторон следует учитывать меньшие значения). Для областей с более длинными сторонами требуется использовать GEOPOLY2D для сохранения точности результатов. GEOPOLY2D ожидает координаты в виде пар широты/долготы в градусах; использование радиан даст результаты в плоском пространстве (аналогично POLY2D).

CONTAINS() принимает многоугольник и набор координат на вход и возвращает 1, если точка находится внутри многоугольника, или 0 в противном случае.

SELECT *,CONTAINS(GEOPOLY2D(40.76439, -73.9997, 42.21211, -73.999,  42.21211, -76.123, 40.76439, -76.123), 41.5445, -74.973) AS inside FROM myindex WHERE MATCH('...') AND inside=1;
Last modified: August 28, 2025