Elasticsearch(022):es常見的字段映射類型之地理形狀類型(geo_shape、多邊的複雜的地址形狀)

概念

在上個小節,我們學習了geo_point的數據類型。

這一小節我們來學習geo_shape數據類型,它有助於索引和搜索 任意地理形狀,例如矩形和多邊形。當正在索引的數據或正在執行的查詢包含除點以外的其他形狀時,應使用它

通過上面的概念描述,我們可以得出geo_pointgeo_shape的最大區別是: geo_point表示一個點;geo_shape則表示有多個點連成線組成的形狀。 學過數學的肯定很容易理解。

實際開發中,如果我們的地理座標是一個地理形狀,則可以使用地理形狀數據類型進行插入、查詢文檔。比如說學校、大商場這種面積比較大的地理座標,都需要geo_shape來表示。

  • mapping params

geo_shape映射將geo_json幾何對象映射到geo_shape類型。要啓用它,用戶必須將字段顯式映射到geo_shape類型。

地理形狀數據類型的參數選項

選項 說明 默認值
tree 將使用的PrefixTree實現的名稱:GeohashPrefixTree爲geohash,QuadPrefixTree爲quadtree。 geohash
precision 可以使用此參數代替tree_levels來爲tree_levels參數設置適當的值。該值指定所需的精度,Elasticsearch將計算最佳的tree_levels值以兌現該精度。該值應爲數字,後跟可選的距離單位。有效距離單位包括:英寸,英寸,碼,碼,英里,英里,公里,公里,米,米,釐米,釐米,毫米,毫米。 meters
tree_levels PrefixTree使用的最大層數。這可用於控制形狀表示的精度,從而控制索引多少項。默認爲所選PrefixTree實現的默認值。由於此參數要求對底層實現有一定程度的瞭解,因此用戶可以改用precision參數。但是,Elasticsearch僅在內部使用tree_levels參數,即使您使用precision參數,這也是通過映射API返回的結果 50m
strategy 策略參數定義瞭如何在索引和搜索時表示形狀的方法。它還會影響可用的功能,因此建議讓Elasticsearch自動設置此參數。有兩種可用的策略:遞歸和術語。術語策略僅支持點類型(points_only參數將自動設置爲true),而遞歸策略則支持所有形狀類型。(重要:請參見前綴樹以獲取更多詳細信息) recursive
distance_error_pct 用作PrefixTree關於其精度的提示。默認值爲0.025(2.5%),最大支持值爲0.5。性能注意:如果明確定義了precision或tree_level定義,則此值將默認爲0。這樣可以保證映射中定義的級別的空間精度。對於低誤差的高分辨率形狀(例如,誤差小於0.001的1m大形狀),這可能會導致大量內存使用。爲了提高索引性能(以查詢準確性爲代價),顯式定義tree_level或precision以及合理的distance_error_pct,請注意,較大的形狀將具有更大的誤報率。 0.025
orientation (可選)定義如何解釋多邊形/多多邊形的頂點順序。此參數定義兩個座標系規則(右手或左手)之一,可以用三種不同的方式來指定每個規則。1.右手規則:右,逆時針,逆時針2. 2.左手規則:左,順時針,順時針。默認方向(逆時針)符合OGC標準,該標準以逆時針順序定義外環頂點,而內環頂點(孔)以順時針順序定義。在geo_shape映射中設置此參數可顯式設置geo_shape字段的座標列表的頂點順序,但可以在每個單獨的GeoJSON文檔中覆蓋。 ccw
points_only 將此選項設置爲true(默認爲false)可僅爲點形狀配置geo_shape字段類型(注意:尚不支持多點)。當已知僅索引點時,這將優化geohash和四叉樹的索引和搜索性能。目前,無法對geo_point字段類型執行geo_shape查詢。此選項通過改善geo_shape字段上的點性能來彌合差距,從而使geo_shape查詢在僅點字段上是最佳的。 false
ignore_malformed 如果爲true,則會忽略格式錯誤的geojson形狀。如果爲假(默認),則格式錯誤的geojson形狀會引發異常並拒絕整個文檔。 false
  • 前綴樹

爲了有效地表示索引中的形狀,使用PrefixTree的實現將Shapes轉換爲代表網格正方形的一系列哈希(通常稱爲“柵格”)。樹的概念來自這樣一個事實,即PrefixTree使用多個網格層,每個網格層的精度更高,以表示地球。
可以認爲這是在更高的縮放級別下增加地圖或圖像的細節級別。

es中提供了多個PrefixTree實現。

  • GeohashPrefixTree 對網格正方形使用geohash。Geohash是交錯的緯度和經度的位的base32編碼的字符串。
    因此,哈希越長,它越精確。添加到geohash的每個字符代表另一個樹級別,併爲geohash增加5位精度。Geohash表示一個矩形區域,並具有32個子矩形。Elasticsearch中的最大級別數爲24。

  • QuadPrefixTree 對網格正方形使用四叉樹。與geohash相似,四叉樹將緯度和經度的比特交織在一起,結果哈希被置位。
    四叉樹中的樹級別代表此位集中的2位,每個座標一個。Elasticsearch中四叉樹的最大級別數爲50。

  • 空間策略

PrefixTree實現依賴於SpatialStrategy來將提供的Shape分解爲近似的網格正方形。每種策略都回答以下問題:

  • 可以索引哪種類型的形狀?
  • 可以使用哪些類型的查詢操作和形狀?
  • 每個字段是否支持多個Shape?

提供以下策略實施(具有相應的功能):

策略 支持的形狀 支持的查詢 多個形狀
recursive All INTERSECTS, DISJOINT, WITHIN, CONTAINS(相交,不相交,內含) Yes
term Points INTERSECTS (相交) Yes
  • 準確性

Geo_shape不提供100%的準確性,並且取決於它的配置方式,它可能對INTERSECTSWITHINCONTAINS查詢返回一些誤報,而對DISJOINT查詢返回一些誤報。

爲了減輕這種情況,爲tree_levels參數選擇適當的值並相應地調整期望很重要。例如,一個點可能在特定網格像元的邊界附近,因此可能與僅與它緊鄰的像元匹配的查詢不匹配-即使形狀非常接近該點。

示例使用

比如說我們有一些大商場的地理信息。我們想要實現在某個地理位置附近多少米範圍有哪些大商場?

1. mapping定義

PUT my_index
{
    "mappings": {
        "docs": {
            "properties": {
                "name": {"type": "text"},
                "location": {
                    "type": "geo_shape"
                }
            }
        }
    }
}

2. 添加數據

PUT my_index/docs/1000
{
  "name": "中心商場",
  "location": {
    "type": "point",
    "coordinates": [121.392496,31.245827]
  }
}
PUT my_index/docs/1001
{
  "name": "城北商場",
  "location": {
    "type": "point",
    "coordinates": [121.392496,31.30]
  }
}
PUT my_index/docs/1002
{
  "name": "城南商場",
  "location": {
    "type": "point",
    "coordinates": [121.392496,31.013]
  }
}
PUT my_index/docs/1003
{
  "name": "城西商場",
  "location": {
    "type": "point",
    "coordinates": [121.821,31.245827]
  }
}
PUT my_index/docs/1004
{
  "name": "城東商場",
  "location": {
    "type": "point",
    "coordinates": [122.392496,31.245827]
  }
}

上例中大量的方括號可能看起來讓人困惑,不過實際上 GeoJSON的語法非常簡單.

  1. 用一個數組表示 經緯度 座標點 [lon,lat]

  2. 一組座標點放到一個數組來表示一個多邊形[[lon,lat],[lon,lat], ... ]

  3. 一個多邊形( polygon )形狀可以包含多個多邊形;第一個表示多邊形的外輪廓,後續的多邊形表示第一個多邊形內部的空洞

[
  [[lon,lat],[lon,lat], ... ],  # main polygon
  [[lon,lat],[lon,lat], ... ],  # hole in main polygon
  ...
]

3. 查詢

比如說查詢 查詢指定位置10KM範圍內的大商場信息數據。

GET my_index/docs/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_shape": {
          "location": {
            "shape": {
              "type": "circle",
              "radius": "10km",
              "coordinates": [121.392496, 31.3]
            }
          }
        }       
      }
    }

  }
}

返回結果集

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "my_index",
        "_type": "docs",
        "_id": "1001",
        "_score": 1,
        "_source": {
          "name": "城北商場",
          "location": {
            "type": "point",
            "coordinates": [
              121.392496,
              31.3
            ]
          }
        }
      },
      {
        "_index": "my_index",
        "_type": "docs",
        "_id": "1000",
        "_score": 1,
        "_source": {
          "name": "中心商場",
          "location": {
            "type": "point",
            "coordinates": [
              121.392496,
              31.245827
            ]
          }
        }
      }
    ]
  }
}

發現有兩個商場符合條件。
後面有geo_shape更復雜的應用,在這裏我們的重點和學習geo_shape這種類型概念和簡單使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章