地理距离查询

编辑

匹配 geo_pointgeo_shape 值,这些值在给定地理点的指定距离内。

示例

编辑

假设以下文档已索引

resp = client.indices.create(
    index="my_locations",
    mappings={
        "properties": {
            "pin": {
                "properties": {
                    "location": {
                        "type": "geo_point"
                    }
                }
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="my_locations",
    id="1",
    document={
        "pin": {
            "location": {
                "lat": 40.12,
                "lon": -71.34
            }
        }
    },
)
print(resp1)

resp2 = client.indices.create(
    index="my_geoshapes",
    mappings={
        "properties": {
            "pin": {
                "properties": {
                    "location": {
                        "type": "geo_shape"
                    }
                }
            }
        }
    },
)
print(resp2)

resp3 = client.index(
    index="my_geoshapes",
    id="1",
    document={
        "pin": {
            "location": {
                "type": "polygon",
                "coordinates": [
                    [
                        [
                            13,
                            51.5
                        ],
                        [
                            15,
                            51.5
                        ],
                        [
                            15,
                            54
                        ],
                        [
                            13,
                            54
                        ],
                        [
                            13,
                            51.5
                        ]
                    ]
                ]
            }
        }
    },
)
print(resp3)
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
const response = await client.indices.create({
  index: "my_locations",
  mappings: {
    properties: {
      pin: {
        properties: {
          location: {
            type: "geo_point",
          },
        },
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "my_locations",
  id: 1,
  document: {
    pin: {
      location: {
        lat: 40.12,
        lon: -71.34,
      },
    },
  },
});
console.log(response1);

const response2 = await client.indices.create({
  index: "my_geoshapes",
  mappings: {
    properties: {
      pin: {
        properties: {
          location: {
            type: "geo_shape",
          },
        },
      },
    },
  },
});
console.log(response2);

const response3 = await client.index({
  index: "my_geoshapes",
  id: 1,
  document: {
    pin: {
      location: {
        type: "polygon",
        coordinates: [
          [
            [13, 51.5],
            [15, 51.5],
            [15, 54],
            [13, 54],
            [13, 51.5],
          ],
        ],
      },
    },
  },
});
console.log(response3);
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_distance 过滤器来匹配在另一个地理点指定距离内的 geo_point

resp = client.search(
    index="my_locations",
    query={
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "200km",
                    "pin.location": {
                        "lat": 40,
                        "lon": -70
                    }
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_distance: {
            distance: '200km',
            'pin.location' => {
              lat: 40,
              lon: -70
            }
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my_locations",
  query: {
    bool: {
      must: {
        match_all: {},
      },
      filter: {
        geo_distance: {
          distance: "200km",
          "pin.location": {
            lat: 40,
            lon: -70,
          },
        },
      },
    },
  },
});
console.log(response);
GET /my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "200km",
          "pin.location": {
            "lat": 40,
            "lon": -70
          }
        }
      }
    }
  }
}

使用相同的过滤器来匹配给定距离内的 geo_shape

resp = client.search(
    index="my_geoshapes",
    query={
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "200km",
                    "pin.location": {
                        "lat": 40,
                        "lon": -70
                    }
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'my_geoshapes',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_distance: {
            distance: '200km',
            'pin.location' => {
              lat: 40,
              lon: -70
            }
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my_geoshapes",
  query: {
    bool: {
      must: {
        match_all: {},
      },
      filter: {
        geo_distance: {
          distance: "200km",
          "pin.location": {
            lat: 40,
            lon: -70,
          },
        },
      },
    },
  },
});
console.log(response);
GET my_geoshapes/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "200km",
          "pin.location": {
            "lat": 40,
            "lon": -70
          }
        }
      }
    }
  }
}

为了同时匹配 geo_pointgeo_shape 值,请搜索这两个索引

resp = client.search(
    index="my_locations,my_geoshapes",
    query={
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "200km",
                    "pin.location": {
                        "lat": 40,
                        "lon": -70
                    }
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'my_locations,my_geoshapes',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_distance: {
            distance: '200km',
            'pin.location' => {
              lat: 40,
              lon: -70
            }
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my_locations,my_geoshapes",
  query: {
    bool: {
      must: {
        match_all: {},
      },
      filter: {
        geo_distance: {
          distance: "200km",
          "pin.location": {
            lat: 40,
            lon: -70,
          },
        },
      },
    },
  },
});
console.log(response);
GET my_locations,my_geoshapes/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "200km",
          "pin.location": {
            "lat": 40,
            "lon": -70
          }
        }
      }
    }
  }
}

接受的格式

编辑

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

纬度/经度作为属性
编辑
resp = client.search(
    index="my_locations",
    query={
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "12km",
                    "pin.location": {
                        "lat": 40,
                        "lon": -70
                    }
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_distance: {
            distance: '12km',
            'pin.location' => {
              lat: 40,
              lon: -70
            }
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my_locations",
  query: {
    bool: {
      must: {
        match_all: {},
      },
      filter: {
        geo_distance: {
          distance: "12km",
          "pin.location": {
            lat: 40,
            lon: -70,
          },
        },
      },
    },
  },
});
console.log(response);
GET /my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "12km",
          "pin.location": {
            "lat": 40,
            "lon": -70
          }
        }
      }
    }
  }
}
纬度/经度作为数组
编辑

格式为 [lon, lat],请注意,这里的经度/纬度顺序是为了符合 GeoJSON

resp = client.search(
    index="my_locations",
    query={
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "12km",
                    "pin.location": [
                        -70,
                        40
                    ]
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_distance: {
            distance: '12km',
            'pin.location' => [
              -70,
              40
            ]
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my_locations",
  query: {
    bool: {
      must: {
        match_all: {},
      },
      filter: {
        geo_distance: {
          distance: "12km",
          "pin.location": [-70, 40],
        },
      },
    },
  },
});
console.log(response);
GET /my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "12km",
          "pin.location": [ -70, 40 ]
        }
      }
    }
  }
}
纬度/经度作为 WKT 字符串
编辑

格式为 Well-Known Text

resp = client.search(
    index="my_locations",
    query={
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "12km",
                    "pin.location": "POINT (-70 40)"
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_distance: {
            distance: '12km',
            'pin.location' => 'POINT (-70 40)'
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my_locations",
  query: {
    bool: {
      must: {
        match_all: {},
      },
      filter: {
        geo_distance: {
          distance: "12km",
          "pin.location": "POINT (-70 40)",
        },
      },
    },
  },
});
console.log(response);
GET /my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "12km",
          "pin.location": "POINT (-70 40)"
        }
      }
    }
  }
}
地理哈希
编辑
resp = client.search(
    index="my_locations",
    query={
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "12km",
                    "pin.location": "drm3btev3e86"
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'my_locations',
  body: {
    query: {
      bool: {
        must: {
          match_all: {}
        },
        filter: {
          geo_distance: {
            distance: '12km',
            'pin.location' => 'drm3btev3e86'
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my_locations",
  query: {
    bool: {
      must: {
        match_all: {},
      },
      filter: {
        geo_distance: {
          distance: "12km",
          "pin.location": "drm3btev3e86",
        },
      },
    },
  },
});
console.log(response);
GET /my_locations/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "12km",
          "pin.location": "drm3btev3e86"
        }
      }
    }
  }
}

选项

编辑

以下是过滤器允许的选项

distance

以指定位置为中心的圆的半径。落入此圆内的点被视为匹配项。distance 可以用各种单位指定。请参阅 距离单位

distance_type

如何计算距离。可以是 arc(默认)或 plane(更快,但在长距离和接近两极时不够准确)。

_name

用于标识查询的可选名称字段

validation_method

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

每个文档的多个位置

编辑

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

忽略未映射字段

编辑

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