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 ds = DataStoreFinder.getDataStore(params);
    
    SimpleFeatureType schema=...
    
    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谓词将所有对象过滤出来```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)

时空查询

HBase 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之后
HBase Ganos支持的时间表达方式有多种:
语法 描述
Time / Time 由起始时间和结束时间定义的区间
Duration / Time 在Time之前的时间区间
Time / Duration 在Time之后的时间区间
示例:如用户想查询位于(120E,30N,130E,40N)之中,时间介于2014-01-01T11:45:00与2014-01-01T12:15:00之间的车辆轨迹,那么需要将空间查询和时间查询结合在一起,如下:
String stFilter = “bbox(geom, 120,30,130,40) AND dtg DURING 2014-01-01T11:45:00.000Z/2014-01-01T12:15:00.00
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 filter = “ name = ‘bob’”
val q = new Query(sft.getTypeName, ECQL.toFilter(filter))
SimpleFeatureCollection features=ds.getFeatureSource(schema).getFeatures(query);            
上例查询中对name字段的值做了限制。
### 指定返回列名用户可以通过配置Query对象参数指定具体返回哪些列,
String[] returnFields=… //指定返回字段名
Query query = new Query(schema, ECQL.toFilter(ecqlPredicate));
query.setPropertyNames(returnFields);
SimpleFeatureCollection features=ds.getFeatureSource(schema).getFeatures(query);
### 指定排序方式用户可以通过构建SortBy对象参数指定具体返回哪些列,如:

String sortField=… //指定排序字段名
FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();

SortBy[] sort = new SortBy[]{ff.sort(sortField, order)};

query.setSortBy(sort);
SimpleFeatureCollection features=ds.getFeatureSource(schema).getFeatures(query);