地理边界框查询编辑

匹配与边界框相交的 geo_pointgeo_shape 值。

示例编辑

假设已对以下文档建立索引

response = client.indices.create(
  index: 'my_locations',
  body: {
    mappings: {
      properties: {
        pin: {
          properties: {
            location: {
              type: 'geo_point'
            }
          }
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my_locations',
  id: 1,
  body: {
    pin: {
      location: {
        lat: 40.12,
        lon: -71.34
      }
    }
  }
)
puts response

response = client.indices.create(
  index: 'my_geoshapes',
  body: {
    mappings: {
      properties: {
        pin: {
          properties: {
            location: {
              type: 'geo_shape'
            }
          }
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my_geoshapes',
  id: 1,
  body: {
    pin: {
      location: {
        type: 'polygon',
        coordinates: [
          [
            [
              13,
              51.5
            ],
            [
              15,
              51.5
            ],
            [
              15,
              54
            ],
            [
              13,
              54
            ],
            [
              13,
              51.5
            ]
          ]
        ]
      }
    }
  }
)
puts response
PUT /my_locations
{
  "mappings": {
    "properties": {
      "pin": {
        "properties": {
          "location": {
            "type": "geo_point"
          }
        }
      }
    }
  }
}

PUT /my_locations/_doc/1
{
  "pin": {
    "location": {
      "lat": 40.12,
      "lon": -71.34
    }
  }
}

PUT /my_geoshapes
{
  "mappings": {
    "properties": {
      "pin": {
        "properties": {
          "location": {
            "type": "geo_shape"
          }
        }
      }
    }
  }
}

PUT /my_geoshapes/_doc/1
{
  "pin": {
    "location": {
      "type" : "polygon",
      "coordinates" : [[[13.0 ,51.5], [15.0, 51.5], [15.0, 54.0], [13.0, 54.0], [13.0 ,51.5]]]
    }
  }
}

使用 geo_bounding_box 过滤器匹配与边界框相交的 geo_point 值。要定义边界框,请为两个相对的角提供地理点值。

response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_bounding_box: {
            'pin.location' => {
              top_left: {
                lat: 40.73,
                lon: -74.1
              },
              bottom_right: {
                lat: 40.01,
                lon: -71.12
              }
            }
          }
        }
      }
    }
  }
)
puts response
GET my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "pin.location": {
            "top_left": {
              "lat": 40.73,
              "lon": -74.1
            },
            "bottom_right": {
              "lat": 40.01,
              "lon": -71.12
            }
          }
        }
      }
    }
  }
}

使用相同的过滤器匹配与边界框相交的 geo_shape

response = client.search(
  index: 'my_geoshapes',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_bounding_box: {
            'pin.location' => {
              top_left: {
                lat: 40.73,
                lon: -74.1
              },
              bottom_right: {
                lat: 40.01,
                lon: -71.12
              }
            }
          }
        }
      }
    }
  }
)
puts response
GET my_geoshapes/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "pin.location": {
            "top_left": {
              "lat": 40.73,
              "lon": -74.1
            },
            "bottom_right": {
              "lat": 40.01,
              "lon": -71.12
            }
          }
        }
      }
    }
  }
}

要同时匹配 geo_pointgeo_shape 值,请搜索两个索引

response = client.search(
  index: 'my_locations,my_geoshapes',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_bounding_box: {
            'pin.location' => {
              top_left: {
                lat: 40.73,
                lon: -74.1
              },
              bottom_right: {
                lat: 40.01,
                lon: -71.12
              }
            }
          }
        }
      }
    }
  }
)
puts response
GET my_locations,my_geoshapes/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "pin.location": {
            "top_left": {
              "lat": 40.73,
              "lon": -74.1
            },
            "bottom_right": {
              "lat": 40.01,
              "lon": -71.12
            }
          }
        }
      }
    }
  }
}

查询选项编辑

选项 描述

_name

用于标识过滤器的可选名称字段

validation_method

设置为 IGNORE_MALFORMED 以接受具有无效纬度或经度的地理点,设置为 COERCE 以尝试推断正确的纬度或经度。(默认值为 STRICT)。

接受的格式编辑

geo_point 类型可以接受地理点的不同表示方式非常类似,过滤器也可以接受它

纬度/经度作为属性编辑
response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_bounding_box: {
            'pin.location' => {
              top_left: {
                lat: 40.73,
                lon: -74.1
              },
              bottom_right: {
                lat: 40.01,
                lon: -71.12
              }
            }
          }
        }
      }
    }
  }
)
puts response
GET my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "pin.location": {
            "top_left": {
              "lat": 40.73,
              "lon": -74.1
            },
            "bottom_right": {
              "lat": 40.01,
              "lon": -71.12
            }
          }
        }
      }
    }
  }
}
纬度/经度作为数组编辑

格式为 [经度, 纬度],请注意,此处经度/纬度的顺序是为了符合 GeoJSON

response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_bounding_box: {
            'pin.location' => {
              top_left: [
                -74.1,
                40.73
              ],
              bottom_right: [
                -71.12,
                40.01
              ]
            }
          }
        }
      }
    }
  }
)
puts response
GET my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "pin.location": {
            "top_left": [ -74.1, 40.73 ],
            "bottom_right": [ -71.12, 40.01 ]
          }
        }
      }
    }
  }
}
纬度/经度作为字符串编辑

格式为 纬度,经度

response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_bounding_box: {
            'pin.location' => {
              top_left: 'POINT (-74.1 40.73)',
              bottom_right: 'POINT (-71.12 40.01)'
            }
          }
        }
      }
    }
  }
)
puts response
GET my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "pin.location": {
            "top_left": "POINT (-74.1 40.73)",
            "bottom_right": "POINT (-71.12 40.01)"
          }
        }
      }
    }
  }
}
边界框作为熟知文本 (WKT)编辑
response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_bounding_box: {
            'pin.location' => {
              wkt: 'BBOX (-74.1, -71.12, 40.73, 40.01)'
            }
          }
        }
      }
    }
  }
)
puts response
GET my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "pin.location": {
            "wkt": "BBOX (-74.1, -71.12, 40.73, 40.01)"
          }
        }
      }
    }
  }
}
Geohash编辑
response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_bounding_box: {
            'pin.location' => {
              top_left: 'dr5r9ydj2y73',
              bottom_right: 'drj7teegpus6'
            }
          }
        }
      }
    }
  }
)
puts response
GET my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "pin.location": {
            "top_left": "dr5r9ydj2y73",
            "bottom_right": "drj7teegpus6"
          }
        }
      }
    }
  }
}

当使用 geohash 指定边界框的边缘时,geohash 将被视为矩形。边界框的定义方式是,其左上角对应于 top_left 参数中指定的 geohash 的左上角,其右下角定义为 bottom_right 参数中指定的 geohash 的右下角。

为了指定与 geohash 整个区域匹配的边界框,可以在 top_leftbottom_right 参数中指定 geohash

response = client.search(
  index: 'my_locations',
  body: {
    query: {
      geo_bounding_box: {
        'pin.location' => {
          top_left: 'dr',
          bottom_right: 'dr'
        }
      }
    }
  }
)
puts response
GET my_locations/_search
{
  "query": {
    "geo_bounding_box": {
      "pin.location": {
        "top_left": "dr",
        "bottom_right": "dr"
      }
    }
  }
}

在本例中,geohash dr 将生成边界框查询,其左上角位于 45.0,-78.75,右下角位于 39.375,-67.5

顶点编辑

边界框的顶点可以通过 top_leftbottom_righttop_rightbottom_left 参数设置。无需成对设置值,可以使用简单名称 topleftbottomright 分别设置值。

response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_bounding_box: {
            'pin.location' => {
              top: 40.73,
              left: -74.1,
              bottom: 40.01,
              right: -71.12
            }
          }
        }
      }
    }
  }
)
puts response
GET my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "pin.location": {
            "top": 40.73,
            "left": -74.1,
            "bottom": 40.01,
            "right": -71.12
          }
        }
      }
    }
  }
}

每个文档多个位置编辑

过滤器可以处理每个文档的多个位置/点。一旦单个位置/点与过滤器匹配,该文档将包含在过滤器中

忽略未映射编辑

设置为 true 时,ignore_unmapped 选项将忽略未映射的字段,并且不会匹配此查询的任何文档。这在查询可能具有不同映射的多个索引时非常有用。设置为 false(默认值)时,如果未映射该字段,则查询将引发异常。

关于精度的说明编辑

地理点的精度有限,并且在索引时始终向下舍入。在查询期间,边界框的上边界向下舍入,而下边界向上舍入。因此,由于舍入误差,沿下边界(边界框的底部和左侧边缘)的点可能无法进入边界框。同时,即使位于边缘稍微外部,沿上边界(顶部和右侧边缘)的点也可能被查询选中。纬度上的舍入误差应小于 4.20e-8 度,经度上的舍入误差应小于 8.39e-8 度,这意味着即使在赤道,误差也不到 1 厘米。

由于舍入,地理形状的精度也有限。沿边界框底部和左侧边缘的地理形状边缘可能与 geo_bounding_box 查询不匹配。边界框顶部和右侧边缘稍微外部的地理形状边缘可能仍然与查询匹配。