Агрегация по сетке геоплиток
Многокорзинная агрегация, которая группирует значения geo_point и geo_shape в корзины, представляющие сетку. Полученная сетка может быть разреженной и содержать только ячейки с соответствующими данными. Каждая ячейка соответствует плитке карты, как используется многими онлайн-картографическими сайтами. Каждая ячейка обозначается в формате "{zoom}/{x}/{y}", где zoom равен заданной пользователем точности.
- Ключи высокой точности имеют больший диапазон для x и y и представляют плитки, покрывающие только небольшую область.
- Ключи низкой точности имеют меньший диапазон для x и y и представляют плитки, каждая из которых покрывает большую область.
См. документацию уровней масштаба для понимания, как точность (zoom) коррелирует с размерами на местности. Точность для этой агрегации может быть от 0 до 29 включительно.
Геоплитка с максимальной точностью 29 создаёт ячейки, покрывающие менее 10 см на 10 см земли, поэтому запросы высокой точности могут быть очень затратными в плане ОЗУ и размера результатов. Пожалуйста, обратитесь к примеру ниже, чтобы узнать, как сначала отфильтровать агрегацию по меньшей географической области перед запросом высокой детализации.
Вы можете использовать только geotile_grid для агрегации явно сопоставленного поля geo_point или geo_shape. Если поле geo_point содержит массив, geotile_grid агрегирует все значения массива.
Простой запрос низкой точности
resp = client.indices.create(
index="museums",
mappings={
"properties": {
"location": {
"type": "geo_point"
}
}
},
)
print(resp)
resp1 = client.bulk(
index="museums",
refresh=True,
operations=[
{
"index": {
"_id": 1
}
},
{
"location": "POINT (4.912350 52.374081)",
"name": "NEMO Science Museum"
},
{
"index": {
"_id": 2
}
},
{
"location": "POINT (4.901618 52.369219)",
"name": "Museum Het Rembrandthuis"
},
{
"index": {
"_id": 3
}
},
{
"location": "POINT (4.914722 52.371667)",
"name": "Nederlands Scheepvaartmuseum"
},
{
"index": {
"_id": 4
}
},
{
"location": "POINT (4.405200 51.222900)",
"name": "Letterenhuis"
},
{
"index": {
"_id": 5
}
},
{
"location": "POINT (2.336389 48.861111)",
"name": "Musée du Louvre"
},
{
"index": {
"_id": 6
}
},
{
"location": "POINT (2.327000 48.860000)",
"name": "Musée d'Orsay"
}
],
)
print(resp1)
resp2 = client.search(
index="museums",
size="0",
aggregations={
"large-grid": {
"geotile_grid": {
"field": "location",
"precision": 8
}
}
},
)
print(resp2) response = client.indices.create(
index: 'museums',
body: {
mappings: {
properties: {
location: {
type: 'geo_point'
}
}
}
}
)
puts response
response = client.bulk(
index: 'museums',
refresh: true,
body: [
{
index: {
_id: 1
}
},
{
location: 'POINT (4.912350 52.374081)',
name: 'NEMO Science Museum'
},
{
index: {
_id: 2
}
},
{
location: 'POINT (4.901618 52.369219)',
name: 'Museum Het Rembrandthuis'
},
{
index: {
_id: 3
}
},
{
location: 'POINT (4.914722 52.371667)',
name: 'Nederlands Scheepvaartmuseum'
},
{
index: {
_id: 4
}
},
{
location: 'POINT (4.405200 51.222900)',
name: 'Letterenhuis'
},
{
index: {
_id: 5
}
},
{
location: 'POINT (2.336389 48.861111)',
name: 'Musée du Louvre'
},
{
index: {
_id: 6
}
},
{
location: 'POINT (2.327000 48.860000)',
name: "Musée d'Orsay"
}
]
)
puts response
response = client.search(
index: 'museums',
size: 0,
body: {
aggregations: {
"large-grid": {
geotile_grid: {
field: 'location',
precision: 8
}
}
}
}
)
puts response const response = await client.indices.create({
index: "museums",
mappings: {
properties: {
location: {
type: "geo_point",
},
},
},
});
console.log(response);
const response1 = await client.bulk({
index: "museums",
refresh: "true",
operations: [
{
index: {
_id: 1,
},
},
{
location: "POINT (4.912350 52.374081)",
name: "NEMO Science Museum",
},
{
index: {
_id: 2,
},
},
{
location: "POINT (4.901618 52.369219)",
name: "Museum Het Rembrandthuis",
},
{
index: {
_id: 3,
},
},
{
location: "POINT (4.914722 52.371667)",
name: "Nederlands Scheepvaartmuseum",
},
{
index: {
_id: 4,
},
},
{
location: "POINT (4.405200 51.222900)",
name: "Letterenhuis",
},
{
index: {
_id: 5,
},
},
{
location: "POINT (2.336389 48.861111)",
name: "Musée du Louvre",
},
{
index: {
_id: 6,
},
},
{
location: "POINT (2.327000 48.860000)",
name: "Musée d'Orsay",
},
],
});
console.log(response1);
const response2 = await client.search({
index: "museums",
size: 0,
aggregations: {
"large-grid": {
geotile_grid: {
field: "location",
precision: 8,
},
},
},
});
console.log(response2); PUT /museums
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
POST /museums/_bulk?refresh
{"index":{"_id":1}}
{"location": "POINT (4.912350 52.374081)", "name": "NEMO Science Museum"}
{"index":{"_id":2}}
{"location": "POINT (4.901618 52.369219)", "name": "Museum Het Rembrandthuis"}
{"index":{"_id":3}}
{"location": "POINT (4.914722 52.371667)", "name": "Nederlands Scheepvaartmuseum"}
{"index":{"_id":4}}
{"location": "POINT (4.405200 51.222900)", "name": "Letterenhuis"}
{"index":{"_id":5}}
{"location": "POINT (2.336389 48.861111)", "name": "Musée du Louvre"}
{"index":{"_id":6}}
{"location": "POINT (2.327000 48.860000)", "name": "Musée d'Orsay"}
POST /museums/_search?size=0
{
"aggregations": {
"large-grid": {
"geotile_grid": {
"field": "location",
"precision": 8
}
}
}
} Ответ:
{
...
"aggregations": {
"large-grid": {
"buckets": [
{
"key": "8/131/84",
"doc_count": 3
},
{
"key": "8/129/88",
"doc_count": 2
},
{
"key": "8/131/85",
"doc_count": 1
}
]
}
}
} Запросы высокой точности
При запросе подробных корзин (обычно для отображения карты с "увеличенным масштабом"), следует применять фильтр, такой как geo_bounding_box, чтобы сузить предметную область. В противном случае может быть создано и возвращено потенциально миллионы корзин.
resp = client.search(
index="museums",
size="0",
aggregations={
"zoomed-in": {
"filter": {
"geo_bounding_box": {
"location": {
"top_left": "POINT (4.9 52.4)",
"bottom_right": "POINT (5.0 52.3)"
}
}
},
"aggregations": {
"zoom1": {
"geotile_grid": {
"field": "location",
"precision": 22
}
}
}
}
},
)
print(resp) response = client.search(
index: 'museums',
size: 0,
body: {
aggregations: {
"zoomed-in": {
filter: {
geo_bounding_box: {
location: {
top_left: 'POINT (4.9 52.4)',
bottom_right: 'POINT (5.0 52.3)'
}
}
},
aggregations: {
"zoom1": {
geotile_grid: {
field: 'location',
precision: 22
}
}
}
}
}
}
)
puts response const response = await client.search({
index: "museums",
size: 0,
aggregations: {
"zoomed-in": {
filter: {
geo_bounding_box: {
location: {
top_left: "POINT (4.9 52.4)",
bottom_right: "POINT (5.0 52.3)",
},
},
},
aggregations: {
zoom1: {
geotile_grid: {
field: "location",
precision: 22,
},
},
},
},
},
});
console.log(response); POST /museums/_search?size=0
{
"aggregations": {
"zoomed-in": {
"filter": {
"geo_bounding_box": {
"location": {
"top_left": "POINT (4.9 52.4)",
"bottom_right": "POINT (5.0 52.3)"
}
}
},
"aggregations": {
"zoom1": {
"geotile_grid": {
"field": "location",
"precision": 22
}
}
}
}
}
} Ответ:
{
...
"aggregations": {
"zoomed-in": {
"doc_count": 3,
"zoom1": {
"buckets": [
{
"key": "22/2154412/1378379",
"doc_count": 1
},
{
"key": "22/2154385/1378332",
"doc_count": 1
},
{
"key": "22/2154259/1378425",
"doc_count": 1
}
]
}
}
}
} Запросы с дополнительным фильтром прямоугольника
Агрегация geotile_grid поддерживает необязательный параметр bounds, который ограничивает рассматриваемые ячейки теми, которые пересекают предоставленные границы. Параметр bounds принимает те же форматы прямоугольника, что и запрос гео-прямоугольника. Этот прямоугольник может использоваться с или без дополнительного запроса geo_bounding_box для фильтрации точек до агрегации. Это независимый прямоугольник, который может пересекаться, совпадать или быть непересекающимся с любыми дополнительными запросами geo_bounding_box, определенными в контексте агрегации.
resp = client.search(
index="museums",
size="0",
aggregations={
"tiles-in-bounds": {
"geotile_grid": {
"field": "location",
"precision": 22,
"bounds": {
"top_left": "POINT (4.9 52.4)",
"bottom_right": "POINT (5.0 52.3)"
}
}
}
},
)
print(resp) response = client.search(
index: 'museums',
size: 0,
body: {
aggregations: {
"tiles-in-bounds": {
geotile_grid: {
field: 'location',
precision: 22,
bounds: {
top_left: 'POINT (4.9 52.4)',
bottom_right: 'POINT (5.0 52.3)'
}
}
}
}
}
)
puts response const response = await client.search({
index: "museums",
size: 0,
aggregations: {
"tiles-in-bounds": {
geotile_grid: {
field: "location",
precision: 22,
bounds: {
top_left: "POINT (4.9 52.4)",
bottom_right: "POINT (5.0 52.3)",
},
},
},
},
});
console.log(response); POST /museums/_search?size=0
{
"aggregations": {
"tiles-in-bounds": {
"geotile_grid": {
"field": "location",
"precision": 22,
"bounds": {
"top_left": "POINT (4.9 52.4)",
"bottom_right": "POINT (5.0 52.3)"
}
}
}
}
} Ответ:
{
...
"aggregations": {
"tiles-in-bounds": {
"buckets": [
{
"key": "22/2154412/1378379",
"doc_count": 1
},
{
"key": "22/2154385/1378332",
"doc_count": 1
},
{
"key": "22/2154259/1378425",
"doc_count": 1
}
]
}
}
} Агрегирование полей geo_shape
Агрегирование по полям геофигуры работает почти так же, как и для точек, за исключением того, что одна фигура может учитываться в нескольких плитках. Фигура будет вносить вклад в подсчёт совпадающих значений, если какая-либо часть её фигуры пересекается с этой плиткой. Ниже приведена иллюстрация:
Параметры
| field | (Обязательно, строка) Поле, содержащее индексированные значения геоточки или геофигуры. Должно быть явно сопоставлено как |
| precision | (Необязательно, целое число) Целое число zoom ключа, используемого для определения ячеек/корзин в результатах. По умолчанию |
| bounds | (Необязательно, объект) Прямоугольник, используемый для фильтрации геоточек или геофигуры в каждой корзине. Принимает те же форматы прямоугольника, что и запрос гео-прямоугольника. |
| size | (Необязательно, целое число) Максимальное количество корзин для возврата. По умолчанию 10 000. При обрезке результатов, корзины приоритезируются на основе объёма документов, которые они содержат. |
| shard_size | (Необязательно, целое число) Количество корзин, возвращаемых с каждого фрагмента. По умолчанию |
© 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/search-aggregations-bucket-geotilegrid-aggregation.html