Геометрические типы данных

На текущий момент единственным поддерживаемым Reindexer геометрическим типом является точка на плоскости (в Golang он реализован как [2]float64 или как тип-синоним Point).

Для работы с точками на плоскости может быть использован индекс типа rtree. При создании индекса можно с помощью тегов указать алгоритм, который будет использоваться при его построении. Возможные значения тегов:

  • linear,
  • quadratic,
  • greene,
  • rstar.

Алгоритмы в этом перечне указаны в порядке от оптимизированных для вставки до оптимизированных для поиска. Однако многое зависит от данных. Рекомендуется протестировать, какой вариант больше подходит вам. По умолчанию используется алгоритм rstar.

Пример создания индекса для работы с двумерными точками:

type Item struct {
	id              int     `reindexer:"id,,pk"`
	pointIndexed    Point `reindexer:"point_indexed,rtree,linear"`
	pointNonIndexed Point `json:"point_non_indexed"`
}

Функции для работы с точками в Reindexer

Точками могут быть столбцы в отдельных или joined-неймспейсах либо фиксированные точки в формате ST_GeomFromText("point(1 -3)").

Поиск точек, находящихся в пределах указанного расстояния друг от друга

Для поиска всех точек, расположенных на определенном расстоянии от заданной точки используется функция ST_DWithin(field_name, point, distance). Принимает 3 параметра: первые два — это координаты точек, третий — дистанция.

Пример запроса с условием фильтрации с помощью функции ST_DWithin() (вернет точки, находящиеся в пределах расстояния 5.0 от точки с координатами (1.0, -3.5)):

query := db.Query("test_namespace").DWithin("point_indexed", Point{1.0, -3.5}, 5.0)
SELECT * FROM test_namespace WHERE ST_DWithin(point_indexed, ST_GeomFromText('point(1 -3.5)'), 5.0)
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
  "namespace": "test_namespace",
  "type": "select",
  "filters": [
    {
      "op": "and",
      "cond": "dwithin",
      "field": "point_indexed",
      "value": [
        [
          1,
          -3.5
        ],
        5
      ]
    }
  ]
}'

По умолчанию к найденным точкам не применяется никакая сортировка. Если требуется отсортировать результаты по расстоянию, можно использовать для этого ST_DWithin совместно с ST_Distance.

Определение расстояния между двумя точками

Для сортировки по расстоянию между двумя точками используется функция ST_Distance() , принимающая координаты точек.

Примеры:

Сортировка по расстоянию между точкой из поля location и некоторой фиксированной точкой:

query = db.Query("actors").SortStPointDistance("location", Point{1.0, -3.0}, true)

Сортировка по расстоянию между точкой из поля location и точкой из поля city.center:

query = db.Query("actors").SortStFieldDistance("location", "city.center", true)

Cортировка по расстоянию между точкой из поля location и некоторой фиксированной точкой:

SELECT * FROM actors ORDER BY 'ST_Distance(location, ST_GeomFromText(\'point(1 -3)\'))' ASC

Сортировка по расстоянию между точкой из поля location и точкой из поля city.center:

SELECT * FROM actors ORDER BY 'ST_Distance(location, city.center)' ASC

Cортировка по расстоянию между точкой из поля location и некоторой фиксированной точкой:

curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
  "namespace": "actors",
  "type": "select",
  "sort": [
    {
      "field": "ST_Distance(location, ST_GeomFromText(\"point(1 -3)\"))",
      "desc": true
    }
  ]
}'

Сортировка по расстоянию между точкой из поля location и точкой из поля city.center:

curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/testdb/query' \
--header 'Content-Type: application/json' \
--data-raw '{
  "namespace": "actors",
  "type": "select",
  "sort": [
    {
      "field": "ST_Distance(location, city.center)",
      "desc": true
    }
  ]
}'