Ganos的数据查询采用GeoTools Query对象来完成,Query中的查询条件是通过构建CQL查询语句来实现的。同时Query还有更多强大的功能,可以指定返回的属性列、对某一属性进行排序等。返回的数据是以SimpleFeatureCollection对象存在,可以通过迭代器遍历所有的SimpleFeature,进而解析出需要的数据。
构造查询条件
查询条件也称之为过滤器(Filter),采用CQL语言描述。CQL功能类似SQL语句的WHERE子句,根据这些条件可以过滤数据。
空间查询
空间查询支持如下谓词,表中的「Expression」表示WKT表示的空间对象(点、线、面):
语法 | 描述 |
INTERSECTS(Expression , Expression) | 判断两个空间对象是否相交,比如两条道路是否相交。 |
DISJOINT(Expression , Expression) | 判断两个空间对象是否相离。 |
CONTAINS(Expression , Expression) | 判断第一个空间对象是否包含第二个空间对象。 |
WITHIN(Expression , Expression) | 与CONTAINS谓词相反,判断第一个对象是否被第二个空间对象包含 。 |
TOUCHES(Expression , Expression) | 两要素边界相交但内部不相交。 |
CROSSES(Expression , Expression) | 判断两个空间要素是否相交,要求仅有部分交集而不是完全包含。 |
BBOX ( Expression , Xmin , Ymin , Xmax , Ymax [ , CRS ]) | 空间对象[Expression]是否与[Xmin,Ymin,Xmax,Ymax]所组成的四边形相交。可选的CRS是空间参考系,包含SRS代码的字符串(例如,'EPSG:1234'。默认使用查询图层的CRS)。 |
示例1:获取某个空间范围(120E,30N,130E,40N)所包含的空间对象(餐馆、船舶、车辆等)。
//获取DataStore DataStore ds = DataStoreFinder.getDataStore(params); //设置查询条件 String schema = "schemaName"; String stFilter = "bbox(geom, 120,30,130,40)" Query query = new Query(schema, ECQL.toFilter(stFilter)); //获取查询结果 SimpleFeatureCollection features=ds.getFeatureSource(schema).getFeatures(query);
示例2:获取周边5公里范围内的所有车辆。
首先将周边5公里的范围构造成空间对象(面),假设为(46.9 48.9, 47.1 48.9, 47.1 49.1, 46.9 49.1, 46.9 48.9)。
使用contains谓词将所有对象过滤出来。
//获取DataStore DataStore ds = DataStoreFinder.getDataStore(params); //设置查询条件 String schema = "schemaName"; String stFilter = "contains(‘POLYGON ((46.9 48.9, 47.1 48.9, 47.1 49.1, 46.9 49.1, 46.9 48.9))’, geom)" Query query = new Query(schema, ECQL.toFilter(stFilter)); //获取查询结果 SimpleFeatureCollection features=ds.getFeatureSource(schema).getFeatures(query);
时空查询
除了空间查询场景以外,还存在大量的时空查询需求。如查询过去2小时内,位于(20E,30N,130E,40N)范围内所有的车辆轨迹。
Lindorm Ganos支持的时间查询谓词如下,表中的「Expression」为时间列名,「Time」为字符串表示的时间(UTC):
语法 | 描述 |
Expression BEFORE Time | 时间在Time之前。 |
Expression BEFORE OR DURING Time Period | 时间在 Time Period之前或包含在 Time Period之中。 |
Expression DURING Time Period | 时间在Time Period之中。 |
Expression DURING OR AFTER Time Period | 时间在Time Period之中或之后。 |
Expression AFTER Time | 时间在Time Period之后。 |
Lindorm Ganos支持的时间表达方式有多种:
语法 | 描述 |
Time / Time | 由起始时间和结束时间定义的区间。 |
Duration / Time | 在Time之前的时间区间。 |
Time / Duration | 在Time之后的时间区间。 |
示例
如用户想查询位于(120E,30N,130E,40N)之中,时间介于2014-01-01T11:45:00与2014-01-01T12:15:00之间的车辆轨迹,那么需要将空间查询和时间查询结合在一起,如下:
//设置查询条件
String schema = "schemaName";
String stFilter = "bbox(geom, 120,30,130,40) AND dtg DURING 2014-01-01T11:45:00.000Z/2014-01-01T12:15:00.000Z";
Query query = new Query(schema, ECQL.toFilter(stFilter));
//获取查询结果
SimpleFeatureCollection features=ds.getFeatureSource(schema).getFeatures(query);
属性查询
比较运算符包括: =,<>,>,>=,<,<=,如要选取人口大于1500万的城市,条件为:PERSONS>15000000,其中PERSONS为人口数量的字段,后面不再单独说明。
BETWEEN表示从一个范围到另一个范围,如PERSONS BETWEEN 1000000 AND 3000000。
比较运算符支持文本值,可在运算符=的右侧指定文本值,如 CITY_NAME='Beijing',表示选择北京市;也可以使用LIKE操作符,与SQL中的用法一样,如 CITY_NAME LIKE 'N%'会选择所有以N开头的城市。
对两个属性进行比较,如 MALE > FEMALE,选择男性多余女性的城市。
算术表达式可以使用 +, -, *, /构成,如过滤条件 UNEMPLOY/(EMPLOYED + UNEMPLOY) > 0.07选择所有失业率大于7%的城市。
使用IN操作符,可选择属性在给定值范围内的,与SQL用法相同,如 ID IN ('cities.1', 'cities.12'),或查找名字在给定值内的城市,可使用 CITY_NAME IN ('Beijing','Shanghai', 'Guangzhou')。
可使用Geoserver中的任何过滤函数,如 strToLowerCase(CITY_NAME) like '%m%',表示名字中包含m的城市,不区分M的大小写。
几何过滤,使用BBOX,比如BBOX(the_geom, -90, 40, -60, 45),表示选择在(-90, 40, -60, 45)范围内的城市。
//设置查询条件 String schema = "schemaName"; String filter = "name = 'bob'"; Query query = new Query(schema, ECQL.toFilter(filter)); //获取查询结果 SimpleFeatureCollection features=ds.getFeatureSource(schema).getFeatures(query);
指定返回列名
用户可以通过配置Query对象参数指定具体返回哪些列,如:
//指定返回字段名
String[] returnFields={"geom"};
//设置查询条件
String schema = "schemaName";
String stFilter = "bbox(geom, 120,30,130,40)"
Query query = new Query(schema, ECQL.toFilter(stFilter));
query.setPropertyNames(returnFields);
//获取查询结果集
SimpleFeatureCollection features=ds.getFeatureSource(schema).getFeatures(query);
指定排序方式
用户可以通过构建SortBy对象参数指定具体返回哪些列,如:
String sortField="name" //指定排序字段名
FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
SortBy[] sort = new SortBy[]{ff.sort(sortField, order)};
query.setSortBy(sort);
SimpleFeatureCollection features=ds.getFeatureSource(schema).getFeatures(query);