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_pointgeo_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"
}

上面的三个点可以在地图上表示如下:

%title插图%num

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 的网格是这样的:

%title插图%num

当精度越低,那么它包含的地理面积就越大,这样极有可能把相近的地理位置点聚合到同一个网格中。从我们返回的数据中,我们可以看得出来 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 文件:

%title插图%num

从上面,我们可以看出来,它包含 Amsterdam 及Antwerp 两个位置,而另外一幅图则包含Paris:

%title插图%num

使用 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 是一个需要版权才可以实现的功能。我们需要启动白金版试用功能:

%title插图%num

%title插图%num

我们再次执行上面的聚合:

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…

Tags: