ジオハッシュグリッド集約

複数のバケット集約で、geo_pointgeo_shape の値をグリッドを表すバケットにグループ化します。結果として得られるグリッドはまばらで、マッチするデータを持つセルのみを含みます。各セルは、ユーザーが定義可能な精度の ジオハッシュ でラベル付けされます。

  • 高精度のジオハッシュは長い文字列の長さを持ち、わずかな面積をカバーするセルを表します。
  • 低精度のジオハッシュは短い文字列の長さを持ち、それぞれが大きな面積をカバーするセルを表します。

この集約で使用されるジオハッシュは、1から12の間で精度を選択できます。

長さ12の最高精度のジオハッシュは、1平方メートル未満の土地をカバーするセルを生成し、高精度のリクエストはRAMと結果サイズの観点から非常にコストがかかる可能性があります。高い詳細レベルをリクエストする前に、集約をより小さな地理的エリアにフィルタリングする方法については、以下の例を参照してください。

geohash_grid を使用して、明示的にマッピングされた geo_point または geo_shape フィールドを集約することができます。geo_point フィールドが配列を含む場合、geohash_grid はすべての配列値を集約します。

シンプルな低精度リクエスト

Python

  1. resp = client.indices.create(
  2. index="museums",
  3. mappings={
  4. "properties": {
  5. "location": {
  6. "type": "geo_point"
  7. }
  8. }
  9. },
  10. )
  11. print(resp)
  12. resp1 = client.bulk(
  13. index="museums",
  14. refresh=True,
  15. operations=[
  16. {
  17. "index": {
  18. "_id": 1
  19. }
  20. },
  21. {
  22. "location": "POINT (4.912350 52.374081)",
  23. "name": "NEMO Science Museum"
  24. },
  25. {
  26. "index": {
  27. "_id": 2
  28. }
  29. },
  30. {
  31. "location": "POINT (4.901618 52.369219)",
  32. "name": "Museum Het Rembrandthuis"
  33. },
  34. {
  35. "index": {
  36. "_id": 3
  37. }
  38. },
  39. {
  40. "location": "POINT (4.914722 52.371667)",
  41. "name": "Nederlands Scheepvaartmuseum"
  42. },
  43. {
  44. "index": {
  45. "_id": 4
  46. }
  47. },
  48. {
  49. "location": "POINT (4.405200 51.222900)",
  50. "name": "Letterenhuis"
  51. },
  52. {
  53. "index": {
  54. "_id": 5
  55. }
  56. },
  57. {
  58. "location": "POINT (2.336389 48.861111)",
  59. "name": "Musée du Louvre"
  60. },
  61. {
  62. "index": {
  63. "_id": 6
  64. }
  65. },
  66. {
  67. "location": "POINT (2.327000 48.860000)",
  68. "name": "Musée d'Orsay"
  69. }
  70. ],
  71. )
  72. print(resp1)
  73. resp2 = client.search(
  74. index="museums",
  75. size="0",
  76. aggregations={
  77. "large-grid": {
  78. "geohash_grid": {
  79. "field": "location",
  80. "precision": 3
  81. }
  82. }
  83. },
  84. )
  85. print(resp2)

Ruby

  1. response = client.indices.create(
  2. index: 'museums',
  3. body: {
  4. mappings: {
  5. properties: {
  6. location: {
  7. type: 'geo_point'
  8. }
  9. }
  10. }
  11. }
  12. )
  13. puts response
  14. response = client.bulk(
  15. index: 'museums',
  16. refresh: true,
  17. body: [
  18. {
  19. index: {
  20. _id: 1
  21. }
  22. },
  23. {
  24. location: 'POINT (4.912350 52.374081)',
  25. name: 'NEMO Science Museum'
  26. },
  27. {
  28. index: {
  29. _id: 2
  30. }
  31. },
  32. {
  33. location: 'POINT (4.901618 52.369219)',
  34. name: 'Museum Het Rembrandthuis'
  35. },
  36. {
  37. index: {
  38. _id: 3
  39. }
  40. },
  41. {
  42. location: 'POINT (4.914722 52.371667)',
  43. name: 'Nederlands Scheepvaartmuseum'
  44. },
  45. {
  46. index: {
  47. _id: 4
  48. }
  49. },
  50. {
  51. location: 'POINT (4.405200 51.222900)',
  52. name: 'Letterenhuis'
  53. },
  54. {
  55. index: {
  56. _id: 5
  57. }
  58. },
  59. {
  60. location: 'POINT (2.336389 48.861111)',
  61. name: 'Musée du Louvre'
  62. },
  63. {
  64. index: {
  65. _id: 6
  66. }
  67. },
  68. {
  69. location: 'POINT (2.327000 48.860000)',
  70. name: "Musée d'Orsay"
  71. }
  72. ]
  73. )
  74. puts response
  75. response = client.search(
  76. index: 'museums',
  77. size: 0,
  78. body: {
  79. aggregations: {
  80. "large-grid": {
  81. geohash_grid: {
  82. field: 'location',
  83. precision: 3
  84. }
  85. }
  86. }
  87. }
  88. )
  89. puts response

Js

  1. const response = await client.indices.create({
  2. index: "museums",
  3. mappings: {
  4. properties: {
  5. location: {
  6. type: "geo_point",
  7. },
  8. },
  9. },
  10. });
  11. console.log(response);
  12. const response1 = await client.bulk({
  13. index: "museums",
  14. refresh: "true",
  15. operations: [
  16. {
  17. index: {
  18. _id: 1,
  19. },
  20. },
  21. {
  22. location: "POINT (4.912350 52.374081)",
  23. name: "NEMO Science Museum",
  24. },
  25. {
  26. index: {
  27. _id: 2,
  28. },
  29. },
  30. {
  31. location: "POINT (4.901618 52.369219)",
  32. name: "Museum Het Rembrandthuis",
  33. },
  34. {
  35. index: {
  36. _id: 3,
  37. },
  38. },
  39. {
  40. location: "POINT (4.914722 52.371667)",
  41. name: "Nederlands Scheepvaartmuseum",
  42. },
  43. {
  44. index: {
  45. _id: 4,
  46. },
  47. },
  48. {
  49. location: "POINT (4.405200 51.222900)",
  50. name: "Letterenhuis",
  51. },
  52. {
  53. index: {
  54. _id: 5,
  55. },
  56. },
  57. {
  58. location: "POINT (2.336389 48.861111)",
  59. name: "Musée du Louvre",
  60. },
  61. {
  62. index: {
  63. _id: 6,
  64. },
  65. },
  66. {
  67. location: "POINT (2.327000 48.860000)",
  68. name: "Musée d'Orsay",
  69. },
  70. ],
  71. });
  72. console.log(response1);
  73. const response2 = await client.search({
  74. index: "museums",
  75. size: 0,
  76. aggregations: {
  77. "large-grid": {
  78. geohash_grid: {
  79. field: "location",
  80. precision: 3,
  81. },
  82. },
  83. },
  84. });
  85. console.log(response2);

コンソール

  1. PUT /museums
  2. {
  3. "mappings": {
  4. "properties": {
  5. "location": {
  6. "type": "geo_point"
  7. }
  8. }
  9. }
  10. }
  11. POST /museums/_bulk?refresh
  12. {"index":{"_id":1}}
  13. {"location": "POINT (4.912350 52.374081)", "name": "NEMO Science Museum"}
  14. {"index":{"_id":2}}
  15. {"location": "POINT (4.901618 52.369219)", "name": "Museum Het Rembrandthuis"}
  16. {"index":{"_id":3}}
  17. {"location": "POINT (4.914722 52.371667)", "name": "Nederlands Scheepvaartmuseum"}
  18. {"index":{"_id":4}}
  19. {"location": "POINT (4.405200 51.222900)", "name": "Letterenhuis"}
  20. {"index":{"_id":5}}
  21. {"location": "POINT (2.336389 48.861111)", "name": "Musée du Louvre"}
  22. {"index":{"_id":6}}
  23. {"location": "POINT (2.327000 48.860000)", "name": "Musée d'Orsay"}
  24. POST /museums/_search?size=0
  25. {
  26. "aggregations": {
  27. "large-grid": {
  28. "geohash_grid": {
  29. "field": "location",
  30. "precision": 3
  31. }
  32. }
  33. }
  34. }

レスポンス:

コンソール結果

  1. {
  2. ...
  3. "aggregations": {
  4. "large-grid": {
  5. "buckets": [
  6. {
  7. "key": "u17",
  8. "doc_count": 3
  9. },
  10. {
  11. "key": "u09",
  12. "doc_count": 2
  13. },
  14. {
  15. "key": "u15",
  16. "doc_count": 1
  17. }
  18. ]
  19. }
  20. }
  21. }

高精度リクエスト

詳細なバケットをリクエストする際(通常は「ズームイン」マップを表示するため)、geo_bounding_box のようなフィルターを適用して対象エリアを狭める必要があります。さもなければ、数百万のバケットが作成され、返される可能性があります。

Python

  1. resp = client.search(
  2. index="museums",
  3. size="0",
  4. aggregations={
  5. "zoomed-in": {
  6. "filter": {
  7. "geo_bounding_box": {
  8. "location": {
  9. "top_left": "POINT (4.9 52.4)",
  10. "bottom_right": "POINT (5.0 52.3)"
  11. }
  12. }
  13. },
  14. "aggregations": {
  15. "zoom1": {
  16. "geohash_grid": {
  17. "field": "location",
  18. "precision": 8
  19. }
  20. }
  21. }
  22. }
  23. },
  24. )
  25. print(resp)

Ruby

  1. response = client.search(
  2. index: 'museums',
  3. size: 0,
  4. body: {
  5. aggregations: {
  6. "zoomed-in": {
  7. filter: {
  8. geo_bounding_box: {
  9. location: {
  10. top_left: 'POINT (4.9 52.4)',
  11. bottom_right: 'POINT (5.0 52.3)'
  12. }
  13. }
  14. },
  15. aggregations: {
  16. "zoom1": {
  17. geohash_grid: {
  18. field: 'location',
  19. precision: 8
  20. }
  21. }
  22. }
  23. }
  24. }
  25. }
  26. )
  27. puts response

Js

  1. const response = await client.search({
  2. index: "museums",
  3. size: 0,
  4. aggregations: {
  5. "zoomed-in": {
  6. filter: {
  7. geo_bounding_box: {
  8. location: {
  9. top_left: "POINT (4.9 52.4)",
  10. bottom_right: "POINT (5.0 52.3)",
  11. },
  12. },
  13. },
  14. aggregations: {
  15. zoom1: {
  16. geohash_grid: {
  17. field: "location",
  18. precision: 8,
  19. },
  20. },
  21. },
  22. },
  23. },
  24. });
  25. console.log(response);

コンソール

  1. POST /museums/_search?size=0
  2. {
  3. "aggregations": {
  4. "zoomed-in": {
  5. "filter": {
  6. "geo_bounding_box": {
  7. "location": {
  8. "top_left": "POINT (4.9 52.4)",
  9. "bottom_right": "POINT (5.0 52.3)"
  10. }
  11. }
  12. },
  13. "aggregations": {
  14. "zoom1": {
  15. "geohash_grid": {
  16. "field": "location",
  17. "precision": 8
  18. }
  19. }
  20. }
  21. }
  22. }
  23. }

geohash_grid 集約によって返されたジオハッシュは、ズームインにも使用できます。前の例で返された最初のジオハッシュ u17 にズームインするには、top_leftbottom_right の両方のコーナーとして指定する必要があります:

Python

  1. resp = client.search(
  2. index="museums",
  3. size="0",
  4. aggregations={
  5. "zoomed-in": {
  6. "filter": {
  7. "geo_bounding_box": {
  8. "location": {
  9. "top_left": "u17",
  10. "bottom_right": "u17"
  11. }
  12. }
  13. },
  14. "aggregations": {
  15. "zoom1": {
  16. "geohash_grid": {
  17. "field": "location",
  18. "precision": 8
  19. }
  20. }
  21. }
  22. }
  23. },
  24. )
  25. print(resp)

Ruby

  1. response = client.search(
  2. index: 'museums',
  3. size: 0,
  4. body: {
  5. aggregations: {
  6. "zoomed-in": {
  7. filter: {
  8. geo_bounding_box: {
  9. location: {
  10. top_left: 'u17',
  11. bottom_right: 'u17'
  12. }
  13. }
  14. },
  15. aggregations: {
  16. "zoom1": {
  17. geohash_grid: {
  18. field: 'location',
  19. precision: 8
  20. }
  21. }
  22. }
  23. }
  24. }
  25. }
  26. )
  27. puts response

Js

  1. const response = await client.search({
  2. index: "museums",
  3. size: 0,
  4. aggregations: {
  5. "zoomed-in": {
  6. filter: {
  7. geo_bounding_box: {
  8. location: {
  9. top_left: "u17",
  10. bottom_right: "u17",
  11. },
  12. },
  13. },
  14. aggregations: {
  15. zoom1: {
  16. geohash_grid: {
  17. field: "location",
  18. precision: 8,
  19. },
  20. },
  21. },
  22. },
  23. },
  24. });
  25. console.log(response);

コンソール

  1. POST /museums/_search?size=0
  2. {
  3. "aggregations": {
  4. "zoomed-in": {
  5. "filter": {
  6. "geo_bounding_box": {
  7. "location": {
  8. "top_left": "u17",
  9. "bottom_right": "u17"
  10. }
  11. }
  12. },
  13. "aggregations": {
  14. "zoom1": {
  15. "geohash_grid": {
  16. "field": "location",
  17. "precision": 8
  18. }
  19. }
  20. }
  21. }
  22. }
  23. }

コンソール結果

  1. {
  2. ...
  3. "aggregations": {
  4. "zoomed-in": {
  5. "doc_count": 3,
  6. "zoom1": {
  7. "buckets": [
  8. {
  9. "key": "u173zy3j",
  10. "doc_count": 1
  11. },
  12. {
  13. "key": "u173zvfz",
  14. "doc_count": 1
  15. },
  16. {
  17. "key": "u173zt90",
  18. "doc_count": 1
  19. }
  20. ]
  21. }
  22. }
  23. }
  24. }

ジオハッシュをサポートしていないシステムで「ズームイン」するためには、バケットキーを利用可能なジオハッシュライブラリの1つを使用してバウンディングボックスに変換する必要があります。たとえば、JavaScriptの場合は、node-geohash ライブラリを使用できます:

Js

  1. var geohash = require('ngeohash');
  2. // bbox will contain [ 52.03125, 4.21875, 53.4375, 5.625 ]
  3. // [ minlat, minlon, maxlat, maxlon]
  4. var bbox = geohash.decode_bbox('u17');

追加のバウンディングボックスフィルタリングを伴うリクエスト

geohash_grid 集約は、提供された境界と交差するセルを考慮する bounds パラメータをサポートしています。bounds パラメータは、Geo Bounding Box Query で指定された境界のすべての同じ 受け入れられた形式 でバウンディングボックスを受け入れます。このバウンディングボックスは、集約前にポイントをフィルタリングする追加の geo_bounding_box クエリとともに、またはそれなしで使用できます。これは独立したバウンディングボックスであり、追加の geo_bounding_box クエリと交差したり、等しい場合や、離れている場合があります。

Python

  1. resp = client.search(
  2. index="museums",
  3. size="0",
  4. aggregations={
  5. "tiles-in-bounds": {
  6. "geohash_grid": {
  7. "field": "location",
  8. "precision": 8,
  9. "bounds": {
  10. "top_left": "POINT (4.21875 53.4375)",
  11. "bottom_right": "POINT (5.625 52.03125)"
  12. }
  13. }
  14. }
  15. },
  16. )
  17. print(resp)

Ruby

  1. response = client.search(
  2. index: 'museums',
  3. size: 0,
  4. body: {
  5. aggregations: {
  6. "tiles-in-bounds": {
  7. geohash_grid: {
  8. field: 'location',
  9. precision: 8,
  10. bounds: {
  11. top_left: 'POINT (4.21875 53.4375)',
  12. bottom_right: 'POINT (5.625 52.03125)'
  13. }
  14. }
  15. }
  16. }
  17. }
  18. )
  19. puts response

Js

  1. const response = await client.search({
  2. index: "museums",
  3. size: 0,
  4. aggregations: {
  5. "tiles-in-bounds": {
  6. geohash_grid: {
  7. field: "location",
  8. precision: 8,
  9. bounds: {
  10. top_left: "POINT (4.21875 53.4375)",
  11. bottom_right: "POINT (5.625 52.03125)",
  12. },
  13. },
  14. },
  15. },
  16. });
  17. console.log(response);

コンソール

  1. POST /museums/_search?size=0
  2. {
  3. "aggregations": {
  4. "tiles-in-bounds": {
  5. "geohash_grid": {
  6. "field": "location",
  7. "precision": 8,
  8. "bounds": {
  9. "top_left": "POINT (4.21875 53.4375)",
  10. "bottom_right": "POINT (5.625 52.03125)"
  11. }
  12. }
  13. }
  14. }
  15. }

コンソール結果

  1. {
  2. ...
  3. "aggregations": {
  4. "tiles-in-bounds": {
  5. "buckets": [
  6. {
  7. "key": "u173zy3j",
  8. "doc_count": 1
  9. },
  10. {
  11. "key": "u173zvfz",
  12. "doc_count": 1
  13. },
  14. {
  15. "key": "u173zt90",
  16. "doc_count": 1
  17. }
  18. ]
  19. }
  20. }
  21. }

赤道でのセルの寸法

以下の表は、さまざまな文字列長のジオハッシュでカバーされるセルのメトリック寸法を示しています。セルの寸法は緯度によって異なり、したがってこの表は赤道での最悪のシナリオに対するものです。

ジオハッシュの長さ 面積の幅 x 高さ
1 5,009.4km x 4,992.6km
2 1,252.3km x 624.1km
3 156.5km x 156km
4 39.1km x 19.5km
5 4.9km x 4.9km
6 1.2km x 609.4m
7 152.9m x 152.4m
8 38.2m x 19m
9 4.8m x 4.8m
10 1.2m x 59.5cm
11 14.9cm x 14.9cm
12 3.7cm x 1.9cm

geo_shape フィールドの集約

Geoshape フィールドの集約は、ポイントと同様に機能しますが、単一の形状が複数のタイルでカウントされる可能性があります。形状の任意の部分がそのタイルと交差する場合、その形状はマッチする値のカウントに寄与します。以下はこれを示す画像です:

geoshape grid

オプション

フィールド 必須。インデックスされたジオポイントまたはジオシェイプの値を含むフィールド。明示的に geo_point または geo_shape フィールドとしてマッピングされている必要があります。フィールドが配列を含む場合、geohash_grid はすべての配列値を集約します。
精度 オプション。結果のセル/バケットを定義するために使用されるジオハッシュの文字列の長さ。デフォルトは5です。精度は、上記の整数精度レベルで定義できます。[1,12] の範囲外の値は拒否されます。
代わりに、精度レベルは「1km」、「10m」のような距離測定から近似できます。精度レベルは、セルが指定されたサイズ(対角線)の必要な精度を超えないように計算されます。これにより、サポートされている12レベルを超える精度レベルが導かれる場合(例:距離が5.6cm未満の場合)、値は拒否されます。
バウンズ オプション。バケット内のポイントをフィルタリングするためのバウンディングボックス。
サイズ オプション。返されるジオハッシュバケットの最大数(デフォルトは10,000)。結果がトリミングされる場合、バケットは含まれるドキュメントのボリュームに基づいて優先されます。
shard_size オプション。最終結果で返されるトップセルのより正確なカウントを可能にするため、集約は各シャードから max(10,(size x number-of-shards)) バケットを返すことをデフォルトとします。このヒューリスティックが望ましくない場合、このパラメータを使用して各シャードから考慮される数をオーバーライドできます。