Elasticsearch:Geo-grid query – Elastic Stack 8.3
2022年8月25日 | by mebius
在我之前的文章 “开始使用 Elasticsearch (3)”,我展示了一些 Geo 查询的一些案例:
- Geo distance 聚合
- Geo bounds 聚合
- Geo centroid 聚合
- Geo tile 聚合
在今天的文章中,我将详述 Geo grid 查询。它用于匹配与 GeoGrid 聚合中的网格单元相交的 geo_point 和 geo_shape 值。该查询旨在通过提供存储桶的键来匹配落在geogrid 聚合存储桶内的文档。 对于 geohash 和 geotile 网格,查询可用于 geo_point 和 geo_shape 字段。 对于 geo_hex 网格,它只能用于 geo_point 字段。
例子
假设以下文档被索引:
PUT /my_locations
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
PUT /my_locations/_doc/1?refresh
{
"location" : "POINT(4.912350 52.374081)",
"city": "Amsterdam",
"name": "NEMO Science Museum"
tgcode}
PUT /my_locations/_doc/2?refresh
{
"location" : "POINT(4.405200 51.222900)",
"city": "Antwerp",
"name": "Letterenhuis"
}
PUT /my_locations/_doc/3?refresh
{
"location" : "POINT(2.336389 48.861111)",
"city": "Paris",
"name": "Muse du Louvre"
}
上面的三个点可以在地图上表示如下:
geohash grid
可能有些开发者对于 geohash 还是不很了解。如果你想了解的话,请阅读我之前的文章 “Elasticsearch:理解 Elastic Maps 中的 geohash 及其聚合”。使用 geohash_grid 聚合,可以根据文档的 geohash 值对文档进行分组:
GET /my_locations/_search?filter_path=aggregations
{
"size" : 0,
"aggs" : {
"grouped" : {
"geohash_grid" : {
"field" : "location",
"precision" : 2
}
}
}
}
在上面,我们请求的精度为 2。上面返回的结果为:
{
"aggregations": {
"grouped": {
"buckets": [
{
"key": "u1",
"doc_count": 2
},
{
"key": "u0",
"doc_count": 1
}
]
}
}
}
我们可以看出来数据被分成两个组。它们分别位于不同的 geohash 的网格中。
当然,我们也可以把精度设置为更低,比如:
GET /my_locations/_search?filter_path=aggregations
{
"size" : 0,
"aggs" : {
"grouped" : {
"geohash_grid" : {
"field" : "location",
"precision" : 1
}
}
}
}
在上面,precision 为 1,那么上面搜索返回的结果为:
{
"aggregations": {
"grouped": {
"buckets": [
{
"key": "u",
"doc_count": 3
}
]
}
}
}
Geohash 的网格是这样的:
当精度越低,那么它包含的地理面积就越大,这样极有可能把相近的地理位置点聚合到同一个网格中。从我们返回的数据中,我们可以看得出来 u0 及 u1 应该是在包含我们上面三个数据的网格里。它们处于 u 的网格中。
geotile grid
有关 geotile grid 的聚合,我有在之前tgcode的文章 “开始使用 Elasticsearch (3)” 中有详述。使用 geotile_grid 聚合,可以根据其 geotile 值对文档进行分组:
GET /my_locations/_search?filter_path=aggregations
{
"size" : 0,
"aggs" : {
"grouped" : {
"geotile_grid" : {
"field" : "location",
"precision" : 6
}
}
}
}
上面的命令返回的结果为:
{
"aggregations": {
"grouped": {
"buckets": [
{
"key": "6/32/21",
"doc_count": 2
},
{
"key": "6/32/22",
"doc_count": 1
}
]
}
}
}
我们可以根据返回的数据的 key 值来显示该桶所在位置的 png 文件:
从上面,我们可以看出来,它包含 Amsterdam 及Antwerp 两个位置,而另外一幅图则包含Paris:
使用 geotile_grid 聚合,可以根据其 geotile 值对文档进行分组:
GET /my_locations/_search?filter_path=**.hits
{
"query": {
"geo_grid" :{
"location" : {
"geotile" : "6/32/22"
}
}
}
}
上面是使用上面返回的 geotile 值 6/32/22 来进行查询的。我可以通过它来确定到底是那个一个文档匹配:
{
"hits": {
"hits": [
{
"_index": "my_locations",
"_id": "3",
"_score": 1,
"_source": {
"location": "POINT(2.336389 48.861111)",
"city": "Paris",
"name": "Muse du Louvre"
}
}
]
}
}
显然它对应于 Paris 这个位置。
geohex grid
使用 geohex_grid 聚合,可以根据其 geohex 值对文档进行分组。特别值得指出的是,geo-hex-agg 是一个需要版权才可以实现的功能。我们需要启动白金版试用功能:
我们再次执行上面的聚合:
GET /my_locations/_search?filter_path=aggregations
{
"size" : 0,
"aggs" : {
"grouped" : {
"geohex_grid" : {
"field" : "location",
"precision" : 1
}
}
}
}
上面聚合的结果为:
{
"aggregations": {
"grouped": {
"buckets": [
{
"key": "81197ffffffffff",
"doc_count": 2
},
{
"key": "811fbffffffffff",
"doc_count": 1
}
]
}
}
}
我们可以通过使用具有以下语法的存储桶tgcode键执行 geo_grid 查询来提取其中一个存储桶上的文档:
GET /my_locations/_search?filter_path=**.hits
{
"query": {
"geo_grid" :{
"location" : {
"geohex" : "811fbffffffffff"
}
}
}
}
上面的命令返回的结果为:
{
"hits": {
"hits": [
{
"_index": "my_locations",
"_id": "3",
"_score": 1,
"_source": {
"location": "POINT(2.336389 48.861111)",
"city": "Paris",
"name": "Muse du Louvre"
}
}
]
}
}
从上面,我们可以看出来 Paris 这个位置处于 geohex 值为811fbffffffffff 的网格中。
文章来源于互联网:Elasticsearch:Geo-grid query – Elastic Stack 8.3
相关推荐: Observability:如何使用 Elastic Agents 把微服务的数据摄入到 Elasticsearch 中
在 Elastic Agents 出现之前,我们有很多方法来把微服务的数据摄入到 Elasticsearch 中。我们可以使用各种语言的 client API 直接写入到 Elasticsearch 中,我们也可以使用 Logstash 或者 Filebeat…