Географические запросы
RethinkDB поддерживает пространственные и географические запросы благодаря поддержке геометрических объектов.
Геометрические объекты реализованы с использованием географической системы координат, где точки и фигуры нанесены на поверхность сферы в трехмерном пространстве. Кроме того, геометрические объекты ReQL могут быть преобразованы в GeoJSON и обратно, с некоторыми ограничениями.
Это общий обзор системы. Для получения более подробной информации обратитесь к документации API для отдельных географических команд.
Начало работы
Создайте новую таблицу:
r.table_create('geo').run(conn)
Добавьте несколько точек:
r.table('geo').insert([
{
:id => 1,
:name => 'San Francisco',
:location => r.point(-122.423246,37.779388)
},
{
:id => 2,
:name => 'San Diego',
:location => r.point(-117.220406,32.719464)
}
]).run(conn)
Получите расстояние между двумя точками в Сан-Франциско и Сан-Диего:
r.table('geo').get(1)['location'].distance(
r.table('geo').get(2)['location']).run(conn)
Добавьте географический индекс в таблицу (необходимый для определенных операций, таких как getNearest):
r.table('geo').index_create('location', {:geo => true})
Получите ближайшую точку в таблице к заданной на основе индекса:
point = r.point(-122.422876,37.777128) # San Francisco
r.table('geo').get_nearest(point, {:index => 'location'})
Система координат
Координаты точек на поверхности сферы задаются парой чисел с плавающей точкой, обозначающих долготу и широту. Диапазон долготы составляет от −180 до 180, что охватывает всю сферу: −180 и 180 обозначают одну и ту же линию. Диапазон широты составляет от −90 (южный полюс) до 90 (северный полюс).
Для более подробного объяснения см. статью Википедии о географической системе координат.
Линии и расстояния
Для двух конечных точек линией в ReQL является кратчайший путь между этими точками на поверхности сферы, называемый геодезической линией. Линии могут быть определены с помощью нескольких точек, в этом случае каждый отрезок линии будет геодезической линией; аналогично, стороны многоугольника будут геодезическими. Геодезические линии рассчитываются, предполагая идеальную сферу.
Обратите внимание, что линию между северным и южным полюсами (от широты −90 до широты 90) нельзя рассчитать, так как все возможные пути между ними являются «кратчайшими»; это может привести к ошибке в ReQL, или ReQL выберет произвольный (но технически правильный) путь.
Расстояния в ReQL (по умолчанию) рассчитываются, предполагая не идеальную сферу, а эллипсоид, используя точный и относительно быстрый алгоритм, разработанный Чарльзом Карни. Используемый эталонный эллипсоид — WGS84, стандарт, используемый для GPS. По умолчанию расстояния указаны в метрах, но вы можете передать необязательный аргумент в функции расстояния, чтобы указать километры, мили, морские мили и футы.
Типы данных
Географические функции реализованы с помощью набора новых типов данных геометрических объектов:
- Точки: пара координат
- Линии: последовательность из двух или более пар координат
- Многоугольники: линия с множеством точек (не менее трех пар координат), которая не пересекает сама себя и у которой первая и последняя пары координат совпадают. Внутренняя часть многоугольника считается заполненной, то есть частью многоугольника. Многоугольники с «дырами» внутри, где дыра — это другой многоугольник, содержащийся в первом, можно создать с помощью команды polygon_sub.
Кроме того, существует «псевдотип» geometry, который встречается в документации, чтобы указать, что любой из геометрических объектов может использоваться с этими командами.
Линии и многоугольники могут быть заданы с помощью объектов точек или последовательностей массивов из двух чисел:
r.line(r.point(0,0), r.point(0,5), r.point(5,5), r.point(5,0), r.point(0,0))
r.line([0,0], [0,5], [5,5], [5,0], [0,0])
Эти определения задают один и тот же квадрат. Если бы polygon было указано вместо line, они определили бы заполненный квадрат.
Хотя есть команда [circle], она приближает круг, определяя либо линию, либо многоугольник. Не существует истинного кругового типа данных.
Географические индексы
Для создания индексов на полях, содержащих геометрические объекты, просто используйте стандартную команду index_create, установив необязательный аргумент geo в значение true. В Ruby это будет:
r.table('sites').index_create('locations', {:geo => true})
Как и другие индексы ReQL, вы можете создать индекс, используя анонимную функцию вместо простого имени поля, а также создать многоуровневые индексы, используя флаг multi с geo. Подробности см. в документации API index_create.
Использование GeoJSON
Геометрические объекты ReQL не являются объектами GeoJSON, но вы можете преобразовывать их друг в друга с помощью команд geojson и to_geojson.
RethinkDB разрешает преобразование только объектов GeoJSON, которые имеют эквиваленты в ReQL: Point, LineString и Polygon; MultiPoint, MultiLineString и MultiPolygon не поддерживаются. (Вы можете, однако, хранить несколько точек, линий и многоугольников в массиве и использовать многоуровневый географический индекс с ними.)
Поддерживаются только координаты долготы/широты. Объекты GeoJSON, использующие декартовы координаты, указывающие высоту или свои собственные системы координат, будут отклонены.
Вопросы и ответы
-
Сколько измерений поддерживается?
Два (широта и долгота). Высота не поддерживается.
-
Какие проекции поддерживаются?
RethinkDB поддерживает эталонный эллипсоид и географическую систему координат (GCS) системы координат WGS84. Он не поддерживает непосредственно проекции систем координат (PCS), но существуют многочисленные инструменты для выполнения таких проекций.
-
RethinkDB корректно интерполирует градусы в метры вдоль пути?
Да. Расчеты расстояний выполняются по геодезической линии (либо эталонный эллипсоид WGS84, либо единичная сфера).
-
Можно ли экспортировать в WKT или WKB?
Нет. Однако вы можете экспортировать в GeoJSON и обработать его другими инструментами.
Географические команды
- geojson: преобразование объекта GeoJSON в геометрический объект
- to_geojson/to_geojson: преобразование геометрического объекта в объект GeoJSON
- point: создание объекта точки
- line: создание объекта линии
- polygon: создание объекта многоугольника
- circle: создание линии или многоугольника, приближающего круг
- distance: вычисление расстояния между точкой и другим геометрическим объектом
- intersects: определение пересечения двух геометрических объектов
- includes: определение, полностью ли один геометрический объект содержится в многоугольном объекте
- get_intersecting: получение документов из последовательности, имеющих геопространственно индексированное поле, значения которого пересекаются с заданным геометрическим объектом
- get_nearest: получение документов из последовательности, имеющих геопространственно индексированное поле, значения которого находятся в заданном расстоянии от заданной точки
- polygon_sub: использование одного многоугольника, полностью содержащегося внутри другого, для вырезания «дыры» во внешнем многоугольнике
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/docs/geo-support/ruby/