地理空间¶
地理空间类型是由经度和纬度坐标组成的复合数据类型,用于表示地理空间数据。GQL 支持三种地理空间类型:Point、LineString 和 Polygon。
为了便于阅读,我们使用 Well-Known Text (WKT) 字符串表示投射在球面上的地理空间值。
Point 类型¶
WKT 格式:POINT(longitude latitude)
Point 类型代表球面上的单个点,由经度和纬度定义。例如,POINT(37.7749 -12.4194),其中37.7749是经度,-12.4194是纬度。
注意,所有地理空间类型的经度取值在-180到180之间,纬度取值在-90到90之间。
LineString 类型¶
WKT 格式:LINESTRING(longitude1 latitude1, longitude2 latitude2, ...)
LineString 类型代表由多条直线连接的点在球面上构成的路径。
每组经度和纬度坐标表示路径中的一个点。例如,LINESTRING(1 2, 2 4, 4 8, 8 16)表示一条从点POINT(1 2)开始,经过POINT(2 4),然后到达POINT(4 8),最后到达POINT(8 16)的路径。
LineString 类型也可以在末尾重复第一个点来表示一条闭合路径。
Polygon 类型¶
WKT 格式:POLYGON((longitude1 latitude1, longitude2 latitude2, ...), ...)
Polygon 类型代表一个具有闭合外边界的形状,该形状内可以包含 0 个或多个孔。它由一系列构成外边界的点,以及构成这些孔的点共同定义。
例如,POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))定义了一个外边界从点POINT(0 0)开始,经过POINT(0 10),然后到达POINT(10 10),接着到达POINT(10 0),最后回到POINT(0 0)的 Polygon。它没有孔。
若要定义包含多个孔的 Polygon,可以参考以下示例:POLYGON((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 4 2, 4 4, 2 4, 2 2), (6 6, 8 6, 8 8, 6 8, 6 6))。在本例中,外边界由第一组点定义,后续的两组点定义了边界内的孔。
在定义 Polygon 时,请注意以下限制:
- 每个 Polygon 必须有闭合的外边界。外边界必须包含至少 4 个点,并且第一和最后一个点必须相同以构成闭合。
- 每个 Polygon 不能自交,即连接点的线段之间不能相互交叉。
- 若 Polygon 包含孔:
- 每个孔也必须由至少 4 个点构成闭合环,第一和最后一个点必须相同。
- 孔之间以及孔与外边界之间不能相互交叉,除非在边界点处。
- 孔必须完全位于外边界内,并且相互不能重叠。
使用示例¶
要使用地理空间类型存储地理空间数据,请参考以下步骤:
-
在图类型定义中声明地理空间类型。
''' CREATE GRAPH TYPE IF NOT EXISTS location AS { NODE Person ( { id INT64 PRIMARY KEY, any_geo Geography(Any), home_location Geography(Point), commute_route Geography(LineString), favorite_area Geography(Polygon) } ), EDGE GEdge (Person)-[LABEL hire {company_location Geography(Point)}]->(Person) } '''声明地理空间类型的语法如下:
Geography(Any)或Geography指代通用的地理空间类型,可以是三种类型中的任何一种(Point、LineString 或 Polygon)。Geography(Point)专指 Point 类型。Geography(LineString)专指 LineString 类型。Geography(Polygon)专指 Polygon 类型。
-
基于声明的图类型创建图。
''' CREATE GRAPH IF NOT EXISTS my_graph TYPED location ''' -
往图中插入数据。注意,插入数据时必须使用地理空间函数生成地理空间类型的值。
插入新的点:
''' USE my_graph INSERT OR REPLACE (@Person {id: 101, any_geo: ST_GeogFromText('POINT(37.7749 -12.4194)'), home_location: ST_GeogFromText('POINT(37.7749 -12.4194)'), commute_route: ST_GeogFromText('LINESTRING(1 2, 2 4, 4 8, 8 16)'), favorite_area: ST_GeogFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))') }), (@Person {id: 102, any_geo: ST_GeogFromText('POINT(34.0522 -18.2437)'), home_location: ST_GeogFromText('POINT(34.0522 -18.2437)'), commute_route: ST_GeogFromText('LINESTRING(3 4, 5 6, 7 8, 9 10)'), favorite_area: ST_GeogFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 4 2, 4 4, 2 4, 2 2))') }) '''基于上述点,插入新的边:
''' USE my_graph Match (n@Person{id:101}), (m@Person{id:102}) INSERT (n)-[@GEdge {company_location: ST_GeogFromText('POINT(37.7749 -12.4194)')}]->(m) ''' -
查询图以检索空间数据。必须使用函数
ST_ASText()将地理空间值转换为 WKT 字符串以便于显示。''' USE my_graph MATCH (p {id:101}) RETURN p.id, ST_ASText(p.home_location) AS home_location, ST_ASText(p.commute_route) AS commute_route, ST_ASText(p.favorite_area) AS favorite_area '''返回:
+------+-------------------------+---------------------------------+----------------------------------------+ | p.id | home_location | commute_route | favorite_area | +------+-------------------------+---------------------------------+----------------------------------------+ | 101 | POINT(37.7749 -12.4194) | LINESTRING(1 2, 2 4, 4 8, 8 16) | POLYGON((0 0, 0 10, 10 10, 10 0, 0 0)) | +------+-------------------------+---------------------------------+----------------------------------------+