Spec-Zone.ru › Elasticsearch 8
›Руководство по Elasticsearch [8.17] ›REST API ›API поиска

API точек во времени

Справочник по новому API

Для получения актуальной информации об API обратитесь к API поиска.

Запрос поиска по умолчанию выполняется с использованием последних видимых данных целевых индексов, что называется точкой во времени. Elasticsearch PIT (точка во времени) — это лёгкий вид данных, как они существовали на момент инициализации. В некоторых случаях предпочтительно выполнять несколько запросов поиска с использованием той же точки во времени. Например, если обновления происходят между запросами `search_after`, результаты этих запросов могут быть не согласованными, так как изменения, произошедшие между запросами, видны только для более поздней точки во времени.

Предварительные условия

  • Если в Elasticsearch включены функции безопасности, у вас должны быть read права на доступ к индексу для целевого потока данных, индекса или псевдонима.

    Для поиска в точке во времени (PIT) для псевдонима, у вас должны быть read права на доступ к индексу для потоков данных или индексов псевдонима.

Тело запроса

index_filter
(Необязательно, объект запроса Позволяет фильтровать индексы, если предоставленный запрос преобразуется в match_none на каждом фрагменте.

Примеры

Точка во времени должна быть явно открыта перед использованием в запросах поиска. Параметр `keep_alive` сообщает Elasticsearch, как долго должна быть активна точка во времени, например, ?keep_alive=5m.

resp = client.open_point_in_time(
    index="my-index-000001",
    keep_alive="1m",
)
print(resp)
response = client.open_point_in_time(
  index: 'my-index-000001',
  keep_alive: '1m'
)
puts response
const response = await client.openPointInTime({
  index: "my-index-000001",
  keep_alive: "1m",
});
console.log(response);
POST /my-index-000001/_pit?keep_alive=1m

Результат вышеуказанного запроса включает id, который следует передать в id параметра pit в запросе поиска.

resp = client.search(
    size=100,
    query={
        "match": {
            "title": "elasticsearch"
        }
    },
    pit={
        "id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==",
        "keep_alive": "1m"
    },
)
print(resp)
const response = await client.search({
  size: 100,
  query: {
    match: {
      title: "elasticsearch",
    },
  },
  pit: {
    id: "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==",
    keep_alive: "1m",
  },
});
console.log(response);
POST /_search  
{
    "size": 100,  
    "query": {
        "match" : {
            "title" : "elasticsearch"
        }
    },
    "pit": {
	    "id":  "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==", 
	    "keep_alive": "1m"  
    }
}

Запрос поиска с параметром pit не должен указывать index, routing или preference, так как эти параметры копируются из точки во времени.

Так же, как и обычные запросы, вы можете использовать from и size для постраничного просмотра результатов поиска, до 10 000 совпадений. Если вам нужно получить больше совпадений, используйте PIT с search_after.

Параметр id сообщает Elasticsearch выполнить запрос, используя контексты из этой точки во времени.

Параметр keep_alive сообщает Elasticsearch, как долго продлить срок действия точки во времени.

Запрос на открытие точки во времени и каждый последующий запрос поиска могут возвращать разные id; поэтому всегда используйте наиболее недавно полученный id для следующего запроса поиска.

В дополнение к параметру keep_alive, можно также определить параметр allow_partial_search_results. Этот параметр определяет, должна ли точка во времени (PIT) допускать недоступные фрагменты или ошибки фрагментов при первоначальном создании PIT. Если установлено значение `true`, PIT будет создан с доступными фрагментами, а также с ссылкой на любые отсутствующие. Если установлено значение `false`, операция завершится ошибкой, если любой фрагмент недоступен. Значение по умолчанию — `false`.

Ответ PIT включает сводку общего количества фрагментов, а также количество успешных фрагментов при создании PIT.

resp = client.open_point_in_time(
    index="my-index-000001",
    keep_alive="1m",
    allow_partial_search_results=True,
)
print(resp)
const response = await client.openPointInTime({
  index: "my-index-000001",
  keep_alive: "1m",
  allow_partial_search_results: "true",
});
console.log(response);
POST /my-index-000001/_pit?keep_alive=1m&allow_partial_search_results=true
{
  "id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=",
  "_shards": {
    "total": 10,
    "successful": 10,
    "skipped": 0,
    "failed": 0
  }
}

Когда PIT, содержащий ошибки фрагментов, используется в запросе поиска, отсутствующие фрагменты всегда сообщаются в ответе поиска как исключение NoShardAvailableActionException. Чтобы избавиться от этих исключений, необходимо создать новый PIT, чтобы фрагменты, отсутствующие в предыдущем PIT, могли быть обработаны, если они станут доступными в промежутке времени.

Поддержание точки во времени активной

Параметр keep_alive, который передаётся в запрос на открытие точки во времени и в запрос поиска, продлевает срок действия соответствующей точки во времени. Значение (например, 1m, см. Единицы времени) не должно быть слишком большим, чтобы обработать все данные — оно должно быть достаточно большим для следующего запроса.

Обычно процесс фоновых слияний оптимизирует индекс, объединяя меньшие сегменты для создания новых, больших сегментов. После того, как меньшие сегменты больше не нужны, они удаляются. Однако открытые точки во времени предотвращают удаление старых сегментов, поскольку они по-прежнему используются.

Поддержание старых сегментов активными означает, что требуется больше места на диске и файловых дескрипторов. Убедитесь, что ваши узлы настроены с достаточным количеством свободных файловых дескрипторов. См. Файловые дескрипторы.

Кроме того, если сегмент содержит удалённые или обновлённые документы, точка во времени должна отслеживать, был ли каждый документ активен на момент первоначального запроса поиска. Убедитесь, что на ваших узлах достаточно оперативной памяти, если у вас много открытых точек во времени в индексе, который подвергается постоянным удалениям или обновлениям. Обратите внимание, что точка во времени не предотвращает удаление связанных с ней индексов.

Вы можете проверить, сколько точек во времени (т.е. контекстов поиска) открыто, с помощью API статистики узлов:

$params = [
    'metric' => 'indices',
    'index_metric' => 'search',
];
$response = $client->nodes()->stats($params);
resp = client.nodes.stats(
    metric="indices",
    index_metric="search",
)
print(resp)
response = client.nodes.stats(
  metric: 'indices',
  index_metric: 'search'
)
puts response
res, err := es.Nodes.Stats(
	es.Nodes.Stats.WithMetric([]string{"indices"}...),
	es.Nodes.Stats.WithIndexMetric([]string{"search"}...),
)
fmt.Println(res, err)
const response = await client.nodes.stats({
  metric: "indices",
  index_metric: "search",
});
console.log(response);
GET /_nodes/stats/indices/search

API точек во времени

Точка во времени автоматически закрывается, когда истекло её keep_alive. Однако хранение точек во времени имеет затраты, как обсуждалось в предыдущем разделе. Точки во времени должны закрываться, как только они больше не используются в запросах поиска.

resp = client.close_point_in_time(
    id="46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==",
)
print(resp)
response = client.close_point_in_time(
  body: {
    id: '46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=='
  }
)
puts response
const response = await client.closePointInTime({
  id: "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==",
});
console.log(response);
DELETE /_pit
{
    "id" : "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
}

API возвращает следующий ответ:

{
   "succeeded": true, 
   "num_freed": 3     
}

Если истинно, все контексты поиска, связанные с идентификатором точки во времени, успешно закрыты

Количество контекстов поиска, которые были успешно закрыты

Нарезка поиска

При просмотре большого количества документов может быть полезно разделить поиск на несколько частей, чтобы потреблять их независимо:

resp = client.search(
    slice={
        "id": 0,
        "max": 2
    },
    query={
        "match": {
            "message": "foo"
        }
    },
    pit={
        "id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
    },
)
print(resp)

resp1 = client.search(
    slice={
        "id": 1,
        "max": 2
    },
    pit={
        "id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
    },
    query={
        "match": {
            "message": "foo"
        }
    },
)
print(resp1)
const response = await client.search({
  slice: {
    id: 0,
    max: 2,
  },
  query: {
    match: {
      message: "foo",
    },
  },
  pit: {
    id: "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==",
  },
});
console.log(response);

const response1 = await client.search({
  slice: {
    id: 1,
    max: 2,
  },
  pit: {
    id: "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA==",
  },
  query: {
    match: {
      message: "foo",
    },
  },
});
console.log(response1);
GET /_search
{
  "slice": {
    "id": 0,                      
    "max": 2                      
  },
  "query": {
    "match": {
      "message": "foo"
    }
  },
  "pit": {
    "id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
  }
}

GET /_search
{
  "slice": {
    "id": 1,
    "max": 2
  },
  "pit": {
    "id": "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
  },
  "query": {
    "match": {
      "message": "foo"
    }
  }
}

Идентификатор части

Максимальное количество частей

Результат первого запроса возвращает документы, принадлежащие первой части (id: 0), а результат второго запроса возвращает документы второй части. Поскольку максимальное количество частей установлено в 2, объединение результатов двух запросов эквивалентно результатам поиска по точке во времени без нарезки. По умолчанию разделение выполняется сначала по фрагментам, затем локально на каждом фрагменте. Локальное разделение разделяет фрагмент на смежные диапазоны на основе идентификаторов документов Lucene.

Например, если количество фрагментов равно 2, а пользователь запросил 4 части, то части 0 и 2 будут назначены первому фрагменту, а части 1 и 3 — второму фрагменту.

Для всех частей должен использоваться один и тот же идентификатор точки во времени. Если используются разные идентификаторы PIT, части могут перекрываться и пропускать документы. Это связано с тем, что критерий разделения основан на идентификаторах документов Lucene, которые не стабильны при изменениях индекса.

© 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/point-in-time-api.html

Spec-Zone.ru

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