为复杂的地理查询选择数据结构/存储解决方案

时间:2018-07-03 14:20:26

标签: elasticsearch redis geolocation postgis tile38

我有一个实体的数据集,其类型和纬度/经度。像这样:

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 km的所有具有大中型房屋的大房子”

什么样的数据结构/存储解决方案就在这里?我查看了ElasticsearchRedis,但看起来我需要遍历给定类型的所有房屋(上面的示例查询为Big)才能回答此问题。

1 个答案:

答案 0 :(得分:1)

PostgreSQLPostGIS直接使用是完全可行的。

考虑您的表结构...

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可以将它们存储在单个GEOGRAPHYGEOMETRY列中。有关更多详细信息,请参见ST_MakePoint。)

  

“查找所有类型为Big的房屋,其中有Small和Medium房屋   半径为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)

(此查询返回的记录距离Big型房屋有1万多米。只需根据您的需要修改第一个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[]