Spec-Zone.ru › Elasticsearch 8
›Elasticsearch Guide [8.17] ›Query DSL ›Geo queries

Запрос расстояния по геоданным

Сопоставляет значения geo_point и geo_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_point, так и geo_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)"
        }
      }
    }
  }
}
Geohash
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 (значение по умолчанию), запрос выбросит исключение, если поле не отображено.

© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/query-dsl-geo-distance-query.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API