1. Introduction
1.介绍
Elasticsearch is best known for its full-text search capabilities but it also features full geospatial support.
Elasticsearch最出名的是它的全文搜索功能,但它也具有全面的地理空间支持。
We can find more about setting up Elasticsearch and getting started in this previous article.
我们可以在这篇前文中找到更多关于设置Elasticsearch和入门的信息。
Let’s take a look on to how we can save geo-data in Elasticsearch and how we can search those data using geo queries.
让我们来看看我们如何在Elasticsearch中保存地理数据,以及如何使用地理查询来搜索这些数据。
2. Geo Data Type
2.地理数据类型[/strong]
To enable geo-queries, we need to create the mapping of the index manually and explicitly set the field mapping.
为了启用地理查询,我们需要手动创建索引的映射,并明确设置字段映射。
Dynamic mapping won’t work while setting mapping for geo types.
在为地理类型设置地图时,动态地图不会工作。。
Elasticsearch offers two ways to represent geodata:
Elasticsearch提供了两种表示地理数据的方式:。
- Latitude-longitude pairs using geo-point field type
- Complex shape defined in GeoJSON using geo-shape field type
Let’s take a more in-depth look at each of the above categories:
让我们更深入地看看上述每个类别:。
2.1. Geo Point Data Type
2.1.地理点数据类型
Geo-point field type accepts latitude-longitude pairs that can be used to:
地理点字段类型接受纬度-经度对,可用于:。
- Find points within a certain distance of central point
- Find points within a box or a polygon
- Aggregate documents geographically or by distance from the central point
- Sort documents by distance
Below is sample mapping for the field to save geo point data:
下面是保存地理点数据的字段的样本映射:
PUT /index_name
{
"mappings": {
"TYPE_NAME": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
}
As we can see from above example, type for location field is geo_point. Thus, we can now provide latitude-longitude pair in the location in the location field.
从上面的例子中我们可以看到,类型为场。400″>location字段是geo_point。因此,我们现在可以在location位置字段中提供纬度-经度对。
2.2. Geo Shape Data Type
2.2.地理形状的数据类型
Unlike geo-point, geo shape provides the functionality to save and search complex shapes like polygon and rectangle. Geo shape data type must be used when we want to search documents that contains shapes other than geo points.
与geo-point不同,geo shape提供了保存和搜索复杂形状的功能,如多边形和矩形。地理形状数据类型必须在我们想要搜索包含地理点以外的形状的文档时使用。
Let’s take a look at mapping for geo shape data type:
让我们来看看地理形状数据类型的映射:。
PUT /index_name
{
"mappings": {
"TYPE_NAME": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
}
Recent versions of Elasticsearch breaks down the provided geo shape into a triangular mesh. According to the official documentation, this provides near perfect spatial resolution.
最近的Elasticsearch版本将所提供的地理形状分解为一个三角形的网格。根据官方的文档,这提供了接近完美的空间分辨率。
3. Different Ways to Save Geo Point Data
3.保存地理点数据的不同方法
3.1. Latitude Longitude Object
3.1.纬度经度对象
PUT index_name/index_type/1
{
"location": {
"lat": 23.02,
"lon": 72.57
}
}
Here, geo-point location is saved as an object with latitude and longitude as keys.
在这里,地理点位置被保存为一个具有纬度和经度作为键。
3.2. Latitude Longitude Pair
3.2.纬度经度对
{
"location": "23.02,72.57"
}
Here, location is expressed as a latitude-longitude pair in a plain string format. Please note, the sequence of latitude and longitude in string format.
这里,location是以普通字符串格式的纬度-经度对表示。请注意,字符串格式的纬度和经度的顺序。
3.3. Geo Hash
3.3.地理杂烩
{
"location": "tsj4bys"
}
We can also provide geo point data in the form of geo hash as shown in the example above. We can use the online tool to convert latitude-longitude to geo hash.
我们也可以以地理哈希的形式提供地理点数据,如上例所示。我们可以使用在线工具来将经纬度转换为地理哈希值。
3.4. Longitude Latitude Array
3.4.经度纬度阵列
{
"location": [72.57, 23.02]
}
The sequence of latitude-longitude is reversed when latitude and longitude are supplied as an array. Initially, the latitude-longitude pair was used in both string and in an array, but later it was reversed in order to match the format used by GeoJSON.
当纬度和经度以数组形式提供时,纬度-经度的顺序被颠倒。最初,纬度-经度对在字符串和数组中都使用,但后来为了配合GeoJSON使用的格式,它被颠倒了。。
4. Different Ways to Save Geo Shape Data
4.保存地理形状数据的不同方法
4.1. Point
4.1.点
POST /index/type
{
"location" : {
"type" : "point",
"coordinates" : [72.57, 23.02]
}
}
Here, the geo shape type that we’re trying to insert is a point. Please take a look at the location field, we have a nested object consisting of fields type and coordinates. These meta-fields help Elasticsearch in identifying the geo shape and its actual data.
在这里,我们试图插入的地理形状类型是一个点。请看一下location字段,我们有一个由type和coordinates字段组成的嵌套对象。这些元字段帮助Elasticsearch识别地理形状和它的实际数据。
4.2. LineString
4.2.LineString
POST /index/type
{
"location" : {
"type" : "linestring",
"coordinates" : [[77.57, 23.02], [77.59, 23.05]]
}
}
Here, we’re inserting linestring geo shape. The coordinates for linestring consists of two points i.e. start and endpoint. LineString geo shape is very helpful for navigation use cases.
在这里,我们要插入linestring地理形状。linestring的坐标由两个点组成,即起点和终点。LineString地理形状对于导航使用案例非常有帮助。
4.3. Polygon
4.3.多边形
POST /index/type
{
"location" : {
"type" : "polygon",
"coordinates" : [
[ [10.0, 0.0], [11.0, 0.0], [11.0, 1.0], [10.0, 1.0], [10.0, 0.0] ]
]
}
}
Here, we’re inserting polygon geo shape. Please take a look at the coordinates in above example, first and last coordinates in polygon should always match i.e a closed polygon.
在这里,我们正在插入polygon地理形状。请看一下上面例子中的坐标,多边形中的第一个和最后一个坐标应该总是匹配的,即一个封闭的多边形。
Elasticsearch also supports other GeoJSON structures as well. A complete list of other supported formats is as below:
Elasticsearch也支持其他GeoJSON结构。其他支持的格式的完整列表如下:。
- MultiPoint
- MultiLineString
- MultiPolygon
- GeometryCollection
- Envelope
- Circle
We can find examples of above-supported formats on the official ES site.
我们可以在官方ES网站上找到上述支持的格式的例子。
For all structures, the inner type and coordinates are mandatory fields. Also, sorting and retrieving geo shape fields are currently not possible in Elasticsearch due to their complex structure. Thus, the only way to retrieve geo fields is from the source field.
对于所有的结构,内部的类型和坐标是强制性的字段。另外,由于地理形状字段的结构复杂,目前在Elasticsearch中无法进行排序和检索。因此,检索地理字段的唯一方法是来自源字段。
5. ElasticSearch Geo Query
5.ElasticSearch的地理查询
Now, that we know how to insert documents containing geo shapes, let’s dive into fetching those records using geo shape queries. But before we start using Geo Queries, we’ll need following maven dependencies to support Java API for Geo Queries:
现在,我们知道了如何插入包含地理形状的文档,让我们深入研究使用地理形状查询来获取这些记录。但在我们开始使用地理查询之前,我们需要以下maven依赖项来支持地理查询的Java API。
<dependency>
<groupId>org.locationtech.spatial4j</groupId>
<artifactId>spatial4j</artifactId>
<version>0.7</version>
</dependency>
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>1.13</version>
<exclusions>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
</exclusions>
</dependency>
We can search for the above dependencies in Maven Central repository as well.
我们也可以在Maven Central资源库中搜索上述依赖项。
Elasticsearch supports different types of geo queries and they are as follow:
Elasticsearch支持不同类型的地理查询,它们如下。
5.1. Geo Shape Query
5.1.地理形状查询[/strong]
This requires the geo_shape mapping.
这需要geo_shape的映射。
Similar to geo_shape type, geo_shape uses GeoJSON structure to query documents.
与geo_shape类型类似,geo_shape使用GeoJSON结构来查询文件。
Below is a sample query to fetch all documents that fall within given top-left and bottom-right coordinates:
下面是一个查询样本,用于获取在给定的左上角和右下角坐标范围内的所有文件。
{
"query":{
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_shape": {
"region": {
"shape": {
"type": "envelope",
"coordinates" : [[75.00, 25.0], [80.1, 30.2]]
},
"relation": "within"
}
}
}
}
}
}
Here, relation determines spatial relation operators used at search time.
这里,关系决定了在搜索时使用的空间关系操作符。
Below is the list of supported operators:
以下是所支持的运营商列表。
- INTERSECTS – (default) returns all documents whose geo_shape field intersects the query geometry
- DISJOINT – retrieves all documents whose geo_shape field has nothing in common with the query geometry
- WITHIN – gets all documents whose geo_shape field is within the query geometry
- CONTAINS – returns all documents whose geo_shape field contains the query geometry
Similarly, we can query using different GeoJSON shapes.
同样地,我们可以使用不同的GeoJSON形状进行查询。
Java code for above query is as below:
上述查询的Java代码如下。
Coordinate topLeft = new Coordinate(74, 31.2);
Coordinate bottomRight = new Coordinate(81.1, 24);
GeoShapeQueryBuilder qb = QueryBuilders.geoShapeQuery("region",
new EnvelopeBuilder(topLeft, bottomRight).buildGeometry());
qb.relation(ShapeRelation.INTERSECTS);
5.2. Geo Bounding Box Query
5.2.地理包围盒查询
Geo Bounding Box query is used to fetch all the documents based on point location. Below is a sample bounding box query:
Geo Bounding Box查询是用来获取基于点位置的所有文件的。下面是一个边界盒查询的例子。
{
"query": {
"bool" : {
"must" : {
"match_all" : {}
},
"filter" : {
"geo_bounding_box" : {
"location" : {
"bottom_left" : [28.3, 30.5],
"top_right" : [31.8, 32.12]
}
}
}
}
}
}
Java code for above bounding box query is as below:
上述包围盒查询的Java代码如下。
QueryBuilders
.geoBoundingBoxQuery("location").setCorners(31.8, 30.5, 28.3, 32.12);
Geo Bounding Box query supports similar formats as we have in geo_point data type. Sample queries for supported formats can be found on the official site.
Geo Bounding Box查询支持与我们在geo_point数据类型中类似的格式。支持的格式的查询样本可以在官方站点上找到。
5.3. Geo Distance Query
5.3.地理距离查询
Geo distance query is used to filter all documents that come with the specified range of the point.
地理距离查询是用来过滤所有带有指定范围的点的文件。
Here’s a sample geo_distance query:
下面是一个geo_distance查询样本。
{
"query": {
"bool" : {
"must" : {
"match_all" : {}
},
"filter" : {
"geo_distance" : {
"distance" : "10miles",
"location" : [31.131,29.976]
}
}
}
}
}
And here’s the Java code for above query:
以下是上述查询的Java代码。
QueryBuilders
.geoDistanceQuery("location")
.point(29.976, 31.131)
.distance(10, DistanceUnit.MILES);
Similar to geo_point, geo distance query also supports multiple formats for passing location coordinates. More details on supported formats can be found at the official site.
与geo_point类似,地理距离查询也支持多种格式来传递位置坐标。关于支持的格式的更多细节可以在官方站点上找到。
5.4. Geo Polygon Query
5.4.GeoPolygon查询
A query to filter all records that have points that fall within the given polygon of points.
一个查询,用于过滤所有具有落在给定的多边形点的记录。
Let’s have a quick look at a sample query:
让我们快速看看一个查询样本。
{
"query": {
"bool" : {
"must" : {
"match_all" : {}
},
"filter" : {
"geo_polygon" : {
"location" : {
"points" : [
{"lat" : 22.733, "lon" : 68.859},
{"lat" : 24.733, "lon" : 68.859},
{"lat" : 23, "lon" : 70.859}
]
}
}
}
}
}
}
And at the Java code for this query:
而在这个查询的Java代码中。
List<GeoPoint> allPoints = new ArrayList<GeoPoint>();
allPoints.add(new GeoPoint(22.733, 68.859));
allPoints.add(new GeoPoint(24.733, 68.859));
allPoints.add(new GeoPoint(23, 70.859));
QueryBuilders.geoPolygonQuery("location", allPoints);
Geo Polygon Query also supports formats mentioned below:
地理多边形查询也支持下面提到的格式。
- lat-long as an array: [lon, lat]
- lat-long as a string: “lat, lon”
- geo hash
geo_point data type is mandatory in order to use this query.
geo_point数据类型是强制性的,以便使用该查询。
6. Conclusion
6.结论
In this article, we discussed different mapping options for indexing geo data i.e geo_point and geo_shape.
在这篇文章中,我们讨论了索引地理数据的不同映射选项,即geo_point和geo_shape。
We also went through different ways to store geo-data and finally, we observed geo-queries and Java API to filter results using geo queries.
我们还经历了存储地理数据的不同方式,最后,我们观察了地理查询和Java API,以使用地理查询过滤结果。
As always, the code is available in this GitHub project.