地理信息搜索(GEO SEARCH)
可以使用Crate的geo_point和geo_shape数据类型来存储和查询很多种类的地理信息。利用这些支持可以用来存储地理位置,道路,形状,区域和其他实体信息。这些信息可以用来查询距离,容量,马路口等,使有可能创建具有丰富地理特性的app和服务。
地理形状使用指定索引存储。地理位置点用它们的坐标来表示。它们表示为相应数据类型的列。
在geo_shape列上使用地理位置索引,以便加速对地理位置甚至复杂形状的搜索。这个索引过程会导致不准确的呈现(查看geo_shape获取更多详情)。Crate不能操作形状矢量,仅仅是一种具有给定精度的格子。
创建包含地理信息的表很简单:
cr> CREATE TABLE country (
... name string,
... country_code string primary key,
... shape geo_shape INDEX USING 'geohash' WITH (precision='100m'),
... capital string,
... capital_location geo_point
... ) WITH (number_of_replicas=0);
CREATE OK (... sec)
这个表将包含一个国家的形状和它的首都的位置以及其他元数据。使用最大精度为100米的geohash索引来索引化位置信息(更多信息,查看Geo形状索引数据结构)。
插入Austria:
cr> INSERT INTO country (mame, country_code, shape, capital, capital_location)
... VALUES (
... 'Austria',
... 'at',
... {type='Polygon', coordinates=[[
... [16.979667, 48.123497], [16.903754, 47.714866],
... [16.340584, 47.712902], [16.534268, 47.496171],
... [16.202298, 46.852386], [16.011664, 46.683611],
... [15.137092, 46.658703], [14.632472, 46.431817],
... [13.806475, 46.509306], [12.376485, 46.767559],
... [12.153088, 47.115393], [11.164828, 46.941579],
... [11.048556, 46.751359], [10.442701, 46.893546],
... [9.932448, 46.920728], [9.47997, 47.10281 ],
... [9.632932, 47.347601], [9.594226, 47.525058],
... [9.896068, 47.580197], [10.402084, 47.302488],
... [10.544504, 47.566399], [11.426414, 47.523766],
... [12.141357, 47.703083], [12.62076, 47.672388],
... [12.932627, 47.467646], [13.025851, 47.637584],
... [12.884103, 48.289146], [13.243357, 48.416115],
... [13.595946, 48.877172], [14.338898, 48.555305],
... [14.901447, 48.964402], [15.253416, 49.039074],
... [16.029647, 48.733899], [16.499283, 48.785808],
... [16.960288, 48.596982], [16.879983, 48.470013],
... [16.979667, 48.123497]]
... },
... 'Vienna',
... [16.372778, 48.209206]
... );
INSERT OK, 1 row affected (... sec)
注意
地理形状必须使用ISO 19107来完全校验。如果你有导入geo数据的问题,他们可能没有完全校验。在大多数情况下,他们将被使用下面的工具来修复:https://github.com/tudelft3d/prepair
地理位置点可以作为一个带有lon和lat的double数组,如上所示或者作为WKT的字符串。
地理形状可以被当做GeoJSON对象或者参数插入,如上所示和WKT的字符串。
当涉及到对你的地理数据有一些有意义的洞察是,Crate支持不同类型的地理查询。
快速查询和利用地理索引的方式是使用Match谓词:
Match Predicate
MATCH谓词可以用来在索引或者索引列上执行多种查询。同时他也可用来执行全文搜索在string类型的分析索引上,有人可以在地理索引上操作,查询地理新装和点的关系。
MATCH (column_ident, query_term) [ using match_type ]
地理搜索的匹配谓词支持将geo_shape索引列的单个column_ident作为第一个参数。
第二个参数,query_term被用来在索引geo_shape之间匹配。
匹配操作有匹配类型match_type决定,match_type将决定我们想要匹配的空间关系。可用的match_type有:
match_type | 详情 |
---|---|
(相交)intersects: | (默认)如果两个形状共享一些点和或者区域,它们是相交的。并且认为会用此匹配类型。这也排除了遏制或完全平等 |
(不相交)disjoint: | 如果两个形状没有共享的点或者区域,则他们是不相交的。这是相交的反面。 |
(包含)within: | 如果索引列column_ident 的形状完全在query_term形状里面,则认为它们使用此匹配类型 |
注意
匹配谓词只能在where子句中使用而且必须为用户创建的表。在MATCH谓词不支持对系统表的操作。注意 一个谓词不能组合所有一个join关系的所有列。
注意 MATCH谓词不能用于连接的两个关系的列,如果它们不能在逻辑上分别应用于它们中的每一个。例如: 这个是允许的: FROM t1, t2 WHERE match(t1.shape, ‘POINT(1.1 2.2)’) AND match(t2.shape, ‘POINT(3.3 4.4)’); 但是这个不允许: FROM t1, t2 WHERE match(t1.shape, ‘POINT(1.1 2.2)’) OR match(t2.shape, ‘POINT(3.3 4.4)’);
cr> SELECT name from countries ... WHERE ... match( ... shape, ... 'LINESTRING (13.3813 52.5229, 11.1840 51.5497, 8.6132 50.0782, 8.3715 47.9457, 8.5034 47.3685)' ... ); +------+ | name | +------+ +------+ SELECT 0 rows in set (... sec)
cr> SELECT name from countries ... WHERE ... match( ... shape, ... 'LINESTRING (13.3813 52.5229, 11.1840 51.5497, 8.6132 50.0782, 8.3715 47.9457, 8.5034 47.3685)' ... ) USING disjoint; +---------+ | name | +---------+ | Austria | +---------+ SELECT 1 row in set (... sec)
精确查询(Exact Queries)
精确查询使用下面标准函数:
- intersects(geo_shape, geo_shape) returns boolean
- within(shape1, shape2) returns boolean
- distance(geo_point1, geo_point2) returns double
他们是精确的,但是这会带来一些性能代价。他们不使用索引但能在GeoJSON上工作,插入计算的形状向量。这个访问代价相当高而且可能减您的查询。为了查询更快,使用Match谓词。
但在有限结果集上执行,他们将帮助您精确洞察您的地理数据:
cr> SELECT within(capital_location, shape) AS capital_in_country
... FROM countries ORDER BY country_code;
+--------------------+
| capital_in_country |
+--------------------+
| TRUE |
+--------------------+
SELECT 1 row in set (... sec)
cr> SELECT distance(capital_location, [0, 0]) as from_northpole
... FROM countries ORDER BY country_code;
+--------------------+
| from_northpole |
+--------------------+
| 1234.2345 |
+--------------------+
SELECT 1 row in set (... sec)
cr> SELECT intersects(
... {type='LineString', coordinates=[[13.3813, 52.5229],
[11.1840, 51.5497],
[8.6132, 50.0782],
[8.3715, 47.9457],
[8.5034, 47.3685]]},
... shape) as berlin_zurich_intersects
... FROM countries ORDER BY country_code;
+--------------------------+
| berlin_zurich_intersects |
+--------------------------+
| FALSE |
+--------------------------+
SELECT 1 row in set (... sec)
尽管如此,这些标准函数可以在允许使用标准函数的SQL查询中的任何地方使用。