作者:MR.
在地图应用中,最最基础的当然应该是地图的浏览与展示,其次,我认为就是查询了,之后的各种功能或多或少都要依赖于查询结果。本文为查询交互系列文章的第一篇,主要简介其分类、使用入门以及交互。
###IServer查询功能体系:
首先,需要简单了解下超图数据格式(数据结构):
从上面可以看出工作空间其实只是相当于一个索引,当然是比较“丰满”的索引,地图、布局、场景类似。数据都存在数据源里的,数据源是若干数据集的集合,数据集又是若干地物的集合,这里的地物是带属性的。IServer发布工作空间也只是在其配置文件里写了几行,其中包括工作空间位置(文件型的是相对路径或绝对路径,数据库型的是数据库链接字符串)等。
了解了大体数据结构也就能更好地理解IServer查询功能了,其中除了布局都能查询,iClient JS主要还是二维的,在此不介绍三维的部分,三维的部分请使用iClient for 3D。
IServer的查询分为地图服务的查询、数据服务的查询以及其他查询。
IServer的地图服务可以发布的类型有很多比如REST、WMS、WMTS等,支持查询的主要是指REST地图服务,WMS包括在其他查询里。地图服务顾名思义是基于地图的服务,根据前面的内容可以得到:IServer通过工作空间读取到地图,根据地图读取到数据集,然后根据地图里对数据集样式、属性的设置来可视化德呈现地图。所以,地图服务的查询只能查询当前地图里存在的、指向数据集的图层,部分专题图图层除外。部分专题图图层除外(在IDesktop图层管理器有“+”号、可以点击展开的专题图图层除外)的原因也很好理解,专题图图层存储方式类似地图,而且它是依赖于地图中存在的指向数据集的图层,所以可以直接查询制作专题图的图层就行了,甚至这个图层不需要显示在地图上,只要它出现在地图图层列表里就行,也就是IDesktop图层管理器里。
IServer的数据服务是直接对数据源操作的服务,是IServer高级版才能使用的模块,上面的地图服务是基础功能,是所有IServer版本都有的模块。数据服务是直接对工作空间下的数据源(集合)及其下的数据集(集合)进行操作,当然也包括查询,这里只讨论查询功能。
其他查询比较多,包括前面有提到的WMS服务的查询,归到这儿是因为他是OGC标准的,OGC已经定义了该WEB服务支持的操作,所有支持OGC标准的开发框架都可以调用它;另外就是IServer其他模块了,空间分析、交通网络分析、交通换乘分析、三维相关功能等都涉及到查询或者有单独的查询功能。
本文讨论地图服务的查询及交互。
###地图服务的查询
地图服务的查询在iClient for JavaScript类参考里是在SuperMap.REST的Query分组下,QueryService、QueryParameters、QueryResult这三个是特别的类,分别是查询服务类、查询参数类和查询结果类的基类,而各种查询服务都是继承他们,也是分为这三种,下面介绍使用方式(以SQL查询为例):
function QuerybySQL()
{
//1.定义查询服务
var QueryBySQLService=new SuperMap.REST.QueryBySQLService(url, //地图服务URL,到地图名那级
{eventListeners: {
"processCompleted": queryCompleted, //查询完成执行函数queryCompleted
"processFailed": queryError //查询失败执行函数queryError
}
}
);
//2.定义查询参数
var queryBySQLParams = new SuperMap.REST.QueryBySQLParameters({
queryOption:"ATTRIBUTEANDGEOMETRY", //查询结果类型枚举,该值为默认值,即返回地物和属性
queryParams: [new SuperMap.REST.FilterParameter({
name: "China_Town_P@China400", //查询图层名,name和smid是该图层属性表字段之一
attributeFilter: "name like '%一%' or smid<=5",//查询条件,相当于SQL语句WHERE部分
orderBy:"smid ASC,name DESC", //查询结果按smid字段升序排列,相当于SQL语句ORDERBY语句部分
fields:['name','smid'] //返回结果字段
}),new SuperMap.REST.FilterParameter({
name: "China_Province_R@China400",
attributeFilter: "name like '%台湾%' or user_from like '%台湾%'",
orderBy:"USER_LEVEL,SmArea",
groupBy:"USER_LEVEL having count(*)=1" //相当于SQL groupBy语句
})] // 查询过滤条件数组
});
//3.发送请求
QueryBySQLService.processAsync(queryBySQLParams);//将参数异步发送给服务器
}
function queryCompleted(QueryResult)//传给回调函数的参数是SuperMap.REST.QueryResult或它的子类
{
console.log(QueryResult);
}
function queryError(QueryResult)
{
console.log(QueryResult);
alert(QueryResult.error.errorMsg);
}
对上面代码的解读:(参照iClient JS API类参考的构造函数,上面代码中有的参数不是必填的,由于面对象的特性,类参考没有列出继承得到的属性、方法,使用时需要注意)
关于name,这里是填图层名(可能出现图层名有.1 .2的情况),具体原因帮助文档有说,这里简单概括下就是一个地图里可以添加多个同名图层并且指向同一个数据集。图层名可以通过直接在浏览器访问地图服务URL,在maps/map/layers/layer下获取相关信息;字段名可以通过数据服务查看,字段值可以先查询再通过返回结果查看;当然如果有备份的数据,直接在IDesktop打开会方便一些;最后上述信息均可通过IServer提供的REST API获得,实际上所有iClient都封装使用了IServer的REST API(可以参考IServer帮助文档)。
一个服务类的对象只能向服务端发送一个参数类的对象.
一个参数类的对象可以设置多个过滤(查询)条件(FilterParameter)类的对象,并且按照过滤条件数组长度对查询结果分组,即,结果类里的recordsets数组,这在某些情况下会很有用。
一个过滤条件类的对象可以设置多个JoinItems进行关联查询(不推荐使用LinkItems)
从上面的代码中可以看到一点灵活的使用,FilterParameter属性里相当于SQL语句某子句的部分是真的可以当成SQL语句写的,它们可以组合使用,可惜的是并没有给出Select甚至直接写SQL语句的属性。
请参照类参考进行使用,相信上面已经让你有了些思考和灵感了。
地图服务的其他几种查询与此类似,除了切片和海图都会涉及到FilterParameter、JoinItems类,与SQL查询的区别只是查询参数类(QueryParameters)略有差别而已,可以参照类参考传入适当的参数,比如几何图形。
###查询结果处理与交互
查询参数类的returnContent参数可以让IServer返回JSON或者是资源URL(在服务端生成新的临时数据集,返回该临时数据集的jsonp资源URL及资源ID),后者涉及IServer临时资源以及REST API,这里只讨论前者,也即直接将查询结果传给回调函数的参数,即iCLient JS里的SuperMap.REST.QueryResult类,客户端已经对结果进行解析了,在浏览器里可以看到返回的结果:
QueryBySQLParameters.queryOption是个枚举类型,非必填参数,表示返回结果类型,默认值是返回属性和地物,因此,我们看到返回结果记录集里的features数组是包含Geometry(矢量图形)和attributes(属性)的,实际上features数组里的对象就是可以直接添加到Vector图层(客户端绘制的图层,参考博客:iClient for JavaScript VectorLayer详细使用指南)上的SuperMap.Feature.Vector对象。
对数据的处理不做过多的描述,交互的部分可以交给客户端图层来做,也可以自定义,比如按钮等等,具体实现有太多。这里简单举一个例子。
分析:
鼠标移动获取区域信息(高亮另可用矢量瓦片,参考SuperMap iClient for JavaScript矢量分块图层-地图快速渲染的利器),可以用客户端图层,这里采用属性图(UTFGrid,详见代码注释、iClient JS API示例和类参考以及博客:IServer缓存介绍).根据属性SQL查询面
根据面查询点,使用几何查询。
添加点击事件。
实现:参阅 完整代码 (附使用REST API获取图层列表)。
效果: