Выбор структуры данных / решение для хранения сложных гео-запросов - PullRequest
0 голосов
/ 03 июля 2018

У меня есть набор данных сущностей с их типом и широтой / долготой. Как это:

Name    Type Lat Long
House1  Big   1   2
House11  Bigger   2   2
House12  Biggest   3   2
House13  Small   4   2
House14  Medium 5   2

Итак, это дома с их типом и местоположением. Теперь мне нужно ответить на такие вопросы, как: «Найти все дома типа Большой, у которых есть Малый и Средний дом в радиусе 10 км»

Какое решение для структуры данных / хранения данных будет здесь? Я посмотрел на Elasticsearch и Redis , но похоже, что мне нужно перебрать все дома данного типа (Большой для примера запроса выше), чтобы ответить на этот вопрос.

1 Ответ

0 голосов
/ 03 июля 2018

Это вполне выполнимо прямо из PostgreSQL с PostGIS.

Учитывая вашу структуру таблицы ...

CREATE TEMPORARY TABLE t (name TEXT, type TEXT, geom GEOGRAPHY);

... и ваши тестовые данные ...

INSERT INTO t VALUES ('House1','Big', ST_MakePoint(1,2));
INSERT INTO t VALUES ('House11','Bigger', ST_MakePoint(2,2));
INSERT INTO t VALUES ('House12','Biggest', ST_MakePoint(3,2));
INSERT INTO t VALUES ('House13','Small', ST_MakePoint(4,2));
INSERT INTO t VALUES ('House14','Medium', ST_MakePoint(5,2));

(Примечание: здесь не имеет смысла разделять lat, long на разные столбцы. PostGIS может хранить оба в одном GEOGRAPHY или GEOMETRY столбце. См. ST_MakePoint для более подробной информации.)

"Найдите все дома типа Большой, в которых есть Малый и Средний дом его радиус 10 км "

Попробуйте что-то подобное, используя ST_Distance:

WITH j AS (SELECT * FROM t WHERE type = 'Big')
SELECT 
  j.name,j.type, 
  ST_Distance(j.geom,t.geom) AS distance, 
  t.name, t.type
FROM j,t 
WHERE 
  ST_Distance(j.geom,t.geom) > 10000 AND
  t.type IN ('Small','Medium');


  name  | type |    distance     |  name   |  type  
--------+------+-----------------+---------+--------
 House1 | Big  |  333756.3481116 | House13 | Small
 House1 | Big  | 445008.41595616 | House14 | Medium
(2 Zeilen)

(Этот запрос возвращает записи, которые находятся на расстоянии более 10 тысяч метров от дома типа Big. Просто адаптируйте первый оператор where для своих нужд)

РЕДАКТИРОВАТЬ: Запрос на основе комментариев.

WITH j AS (SELECT *, ARRAY(SELECT DISTINCT t2.type 
               FROM t t2
                   WHERE t2.type IN ('Small','Medium') AND 
               ST_Distance(t2.geom,t1.geom) < 100000
                   ) AS nearHouseType 
       FROM t t1 WHERE type = 'Big')
SELECT *
FROM j
WHERE j.nearHouseType @> '{Medium, Small}'::TEXT[]
...