Skip to content

Instantly share code, notes, and snippets.

@abruzzi
Last active August 29, 2015 14:01
Show Gist options
  • Save abruzzi/eb5e6bbc975ff1233a00 to your computer and use it in GitHub Desktop.
Save abruzzi/eb5e6bbc975ff1233a00 to your computer and use it in GitHub Desktop.
ArcGIS Tools for Hadoop

ArcGIS Tools for hadoop 使用

ArcGIS Tools for hadoop,简称ATH(下同)由三个组件组成:几何计算包空间计算包ArcGIS桌面工具

我们这篇文档主要关注前两个。几何计算是一个独立的jar包,空间计算包是一个Hive的扩展,因此需要Hive环境才能运行。

设置环境

此处下载样例包,解压后,samples目录中为几个示例,我们此处将使用point-in-polygon-aggregation-hive。

这个示例是这样的:

  1. 已知一些表示地震的点的集合
  2. 已知一些表示郡县的多边形的集合

求每个郡县中的地震次数。

这个场景显然是一个典型的适合Hadoop进行计算的场景:求和。

Hive代码
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环境中加入额外的jar包

首先,需要在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';

这里有两点需要注意:

  1. LOCATION的值中,指定了一个目录(earthquake-data)
  2. 如何表已经存在,这段代码则不会被执行

如何此时执行

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment