ArcGIS Tools for hadoop,简称ATH(下同)由三个组件组成:几何计算包,空间计算包,ArcGIS桌面工具。
我们这篇文档主要关注前两个。几何计算是一个独立的jar包,空间计算包是一个Hive的扩展,因此需要Hive环境才能运行。
在此处下载样例包,解压后,samples目录中为几个示例,我们此处将使用point-in-polygon-aggregation-hive。
这个示例是这样的:
- 已知一些表示地震的点的集合
- 已知一些表示郡县的多边形的集合
求每个郡县中的地震次数。
这个场景显然是一个典型的适合Hadoop进行计算的场景:求和。
SELECT counties.name, count(*) cnt FROM counties
JOIN earthquakes
WHERE ST_Contains(counties.boundaryshape, ST_Point(earthquakes.longitude, earthquakes.latitude))
GROUP BY counties.name
ORDER BY cnt desc;
得到的结果是
Kern 36
San Bernardino 35
Imperial 28
Inyo 20
Los Angeles 18
Riverside 14
Monterey 14
Santa Clara 12
Fresno 11
San Benito 11
San Diego 7
Santa Cruz 5
San Luis Obispo 3
Ventura 3
Orange 2
San Mateo 1
那么,如何运行这段(SQL)代码呢?
首先,需要在Hive环境中添加ArcGIS的两个包:几何计算包,空间计算包
进入Hive环境:
$ hive
...
...
hive> _
然后输入:
add jar
/home/hduser/esri-git/gis-tools-for-hadoop/samples/lib/esri-geometry-api.jar
/home/hduser/esri-git/gis-tools-for-hadoop/samples/lib/spatial-sdk-hadoop.jar;
注意,Hive命令的结尾字符为分号,表示一行的结束。
由于ArcGIS提供的数据是json格式和csv格式,因此我们需要先将这些数据导入到Hive中:
CREATE EXTERNAL TABLE IF NOT EXISTS earthquakes (earthquake_date STRING, latitude DOUBLE, longitude DOUBLE, magnitude DOUBLE)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '${env:HOME}/esri-git/gis-tools-for-hadoop/samples/data/earthquake-data';
这里有两点需要注意:
- LOCATION的值中,指定了一个目录(earthquake-data)
- 如何表已经存在,这段代码则不会被执行
如何此时执行
select count(*) from earthquakes;
就会得到结果0,这是因为Location指定的文件并不存在,我们需要将实际的物理文件存储到HDFS中:
$ hadoop fs -mkdir -p /home/hduser/esri-git/gis-tools-for-hadoop/samples/data/earthquake-data
$ hadoop fs -put esri-git/gis-tools-for-hadoop/samples/data/earthquake-data/earthquakes.csv\
/home/hduser/esri-git/gis-tools-for-hadoop/samples/data/earthquake-data
首先,使用hadoop fs -mkdir -p
创建目录结构,然后使用hadoop fs -put
将本地文件earthquakes.csv推送到HDFS中。
然后再次执行:
select count(*) from earthquakes;
就会看到实际的记录数目了。这一步导入的是CSV格式的文件到Hive中,接下来我们将导入json格式的记录到Hive:
CREATE EXTERNAL TABLE IF NOT EXISTS counties (Area string, Perimeter string, State string, County string, Name string, BoundaryShape binary)
ROW FORMAT SERDE 'com.esri.hadoop.hive.serde.JsonSerde'
STORED AS INPUTFORMAT 'com.esri.json.hadoop.EnclosedJsonInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION '${env:HOME}/esri-git/gis-tools-for-hadoop/samples/data/counties-data';
同样,需要将文件上传到HDFS中。
ATH提供了很多的UTF(用户定义函数,是Hive支持的标准扩展方式),完整的列表可以参考这里。
在实际使用时,我们需要先将这些函数导入
create temporary function ST_Point as 'com.esri.hadoop.hive.ST_Point';
create temporary function ST_Contains as 'com.esri.hadoop.hive.ST_Contains';
导入之后,如果你想要查看这个函数的返回值,参数情况,可以:
desc function ST_Intersects;
会得到详细的说明信息
ST_Intersects(geometry1, geometry2) - return true if geometry1 intersects geometry2
如果频繁的执行诸如此类的实验,你肯定不愿意每次都敲入这么多的内容,和写其他的程序一样,你可以将这些内容写到文件中,然后使用Hive一次性的执行:
add jar
${env:HOME}/gis/gis-tools-for-hadoop/samples/lib/esri-geometry-api.jar
${env:HOME}/gis/gis-tools-for-hadoop/samples/lib/spatial-sdk-hadoop.jar;
create temporary function ST_Point as 'com.esri.hadoop.hive.ST_Point';
create temporary function ST_Contains as 'com.esri.hadoop.hive.ST_Contains';
create temporary function ST_Intersects as 'com.esri.hadoop.hive.ST_Intersects';
CREATE EXTERNAL TABLE IF NOT EXISTS myroads (Name string, Layer string, Shape binary)
ROW FORMAT SERDE 'com.esri.hadoop.hive.serde.JsonSerde'
STORED AS INPUTFORMAT 'com.esri.json.hadoop.EnclosedJsonInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION '${env:HOME}/sampledata/roads';
select myroads.name, count(*) from f_100w
join myroads
where st_intersects(st_point(f_100w.longitude, f_100w.latitude), myroads.shape)=true
group by myroads.name;
保存为roadtest.hive
$ hive -f roadtest.hive