В Elasticsearch документ — это наименьшая единица всех доступных для поиска данных. Он сериализуется в JSON и хранится в Elasticsearch. Каждый документ будет иметь уникальный идентификатор, который вы можете указать самостоятельно или предоставить Elasticsearch для его автоматической генерации.
Продолжая наше предыдущее неуместное сравнение RDMS, я думаю, что документы можно сравнить с таблицами в реляционных базах данных.
метаданные
Как мы упоминали ранее, каждый документ идентифицируется уникальным идентификатором, при получении документа в поле «_id» записывается уникальный идентификатор документа, который является одним из метаданных. Конечно, в документе есть и другие метаданные, давайте представим их по порядку.
- _index: имя индекса, которому принадлежит документ
- _type: тип, к которому принадлежит документ
- _id: уникальный идентификатор документа.
С помощью этих трех мы можем однозначно идентифицировать документ.Конечно, после версии 7.0 нам больше не нужен _type. Далее, давайте посмотрим на некоторые другие метаданные.
- _source: необработанные данные JSON документа
- _field_names: Это поле используется для индексации имени поля в документе, значение которого не равно нулю. В основном оно используется для существующего запроса, чтобы узнать, является ли указанное поле пустым.
- _ignore: это поле используется для индексации и хранения имени каждого поля в документе, которое игнорируется из-за исключений (игнорирование искажений включено).
- _meta: это поле используется для хранения некоторых пользовательских метаданных.
- _routing: используется для указания, на какой сегмент попадают данные, значение по умолчанию — Id.
- _version: информация о версии документа
- _score: оценка релевантности
Создать документацию
Существует 4 способа создания документа:
- PUT /<index>/_doc/<_id>
- POST /<index>/_doc/
- PUT /<index>/_create/<_id>
- POST /<index>/_create/<_id>
Разница между этими четырьмя методами заключается в том, что если вы не укажете идентификатор, Elasticsearch автоматически сгенерирует идентификатор. Если вы используете метод _create, вы должны убедиться, что документ не существует, а с помощью метода _doc вы можете либо создать новый документ, либо обновить существующий документ.
При создании документа также можно выбрать некоторые параметры.
параметры запроса
- if_seq_no: Обновлять только в том случае, если серийный номер документа соответствует указанному значению.
- if_primary_term: Обновлять только в том случае, если основным термином документа является указанное значение.
- op_type: если установлено значение create, документ с указанным идентификатором не должен существовать, иначе операция завершится ошибкой. Допустимые значения — index или create, по умолчанию — index
- op_type: указывает идентификатор предварительно обработанного конвейера.
- refresh: если установлено значение true, затронутые осколки немедленно сбрасываются. Если стоит wait_for, операция не будет видна поиску, пока шард не обновится. Если false, осколки не будут обновляться. Значение по умолчанию — ложь
- routing: указывает основной сегмент для маршрутизации
- timeout: укажите время ответа, по умолчанию 30 секунд.
- master_timeout: Время отклика на подключение к мастер-узлу, по умолчанию 30 секунд.
- version: Явно указать номер версии
- version_type: укажите тип номера версии: internal, external, external_gte, force
- wait_for_active_shards: количество копий сегментов, которые должны оставаться активными перед обработкой операций, для которых можно указать все или любое положительное целое число. Значение по умолчанию — 1, то есть активным должен быть только основной шард.
тело ответа
- _shards: предоставляет информацию об осколках
- _shards.total: Общее количество осколков, для которых были созданы документы.
- _shards.successful: количество успешно созданных фрагментов документа
- _shards.failed: количество осколков, для которых не удалось создать документ.
- _index: Индекс, к которому принадлежит документ
- _type: тип, к которому принадлежит документ, в настоящее время поддерживается только _doc
- _id: идентификатор документа
- _version: номер версии документа
- _seq_no: порядковый номер документа
- _primary_term: основной термин документа
- result: результат индекса, созданный или обновленный
Когда мы создаем документ, если указанный индекс не существует, ES автоматически создаст для нас индекс. Этой операцией можно управлять с помощью поля action.auto_create_index в настройках, которое по умолчанию имеет значение true. Вы можете изменить это поле, чтобы указать, что некоторые индексы могут быть созданы автоматически или что все индексы не могут быть созданы автоматически.
обновить документацию
Поняв, как создать документ, давайте посмотрим, как обновить существующий документ. На самом деле, когда мы создавали документ, мы упомянули, что с помощью метода PUT /
POST /<index>/_update/<_id>
Два обновления разные. Метод _doc заключается в том, чтобы сначала удалить исходный документ, а затем создать новый. Метод _update представляет собой добавочное обновление, процесс обновления которого заключается в том, чтобы сначала получить документ, затем запустить указанный скрипт и, наконец, переиндексировать.
Еще одно отличие состоит в том, что метод _update поддерживает обновление скрипта, язык по умолчанию безболезненный, и вы можете установить его через параметр lang. С точки зрения параметров запроса, _update имеет следующие параметры по сравнению с _doc:
- lang: укажите язык сценариев
- retry_on_conflict: количество повторных попыток при возникновении конфликта, по умолчанию 0
- _source: установлено значение false, поля поиска не возвращаются
- _source_excludes: указывает исходное поле, которое следует исключить из результатов поиска.
- _source_includes: указывает возвращаемое поле источника поиска.
Вот пример использования скрипта для обновления документа
curl -X POST "localhost:9200/test/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
"script" : {
"source": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
}
}
'
Upsert
curl -X POST "localhost:9200/test/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
"script" : {
"source": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
},
"upsert" : {
"counter" : 1
}
}
'
Когда указанный документ не существует, вы можете использовать параметр upsert для создания нового документа, а когда указанный документ существует, запрос выполнит скрипт в скрипте. Если вы не хотите использовать скрипт и хотите просто добавить/обновить документацию, вы можете использовать doc_as_upsert.
curl -X POST "localhost:9200/test/_update/1?pretty" -H 'Content-Type: application/json' -d'
{
"doc" : {
"name" : "new_name"
},
"doc_as_upsert" : true
}
'
update by query
Этот API используется для пакетного обновления извлеченных документов, что можно понять на примере.
curl -X POST "localhost:9200/twitter/_update_by_query?pretty" -H 'Content-Type: application/json' -d'
{
"script": {
"source": "ctx._source.likes++",
"lang": "painless"
},
"query": {
"term": {
"user": "kimchy"
}
}
}
'
Получить документацию
ES использует GET API для получения документов, а формат запроса следующий:
GET /<index>/_doc/<_id>
Он вернет данные документа и некоторые метаданные, если вам нужен только контент документа и вам не нужны метаданные, вы можете использовать
GET /<index>/_source/<_id>
параметры запроса
Некоторые параметры запроса на получение документов уже упоминались ранее и не будут повторяться здесь:
- refresh
- routing
- _source
- _source_excludes
- _source_includes
- version
- version_type
И есть некоторые параметры, которые не упоминались ранее, давайте посмотрим
- preference: используется для указания узла или сегмента для выполнения запроса.Если установлено значение _local, локальный сегмент будет выполняться первым.
- realtime: Если установлено значение true, запрос выполняется в режиме реального времени, а не в режиме, близком к реальному. По умолчанию верно
- stored_fields: возвращает поле, в котором значение store равно true в указанном поле.
mget
mget — один из методов пакетного сбора, существует два формата запроса:
- GET /_mget
- GET /<index>/_mget
Первый — записать индекс в тело запроса. Второй — поместить индекс в URL-адрес, но этот метод может вызвать проверку безопасности ES.
Параметры запроса mget такие же, как у get, за исключением того, что соответствующие условия извлечения doc необходимо указать в теле запроса.
request
GET /_mget
{
"docs" : [
{
"_index" : "jackey",
"_id" : "1"
},
{
"_index" : "jackey",
"_id" : "2"
}
]
}
response
{
"docs" : [
{
"_index" : "jackey",
"_type" : "_doc",
"_id" : "1",
"_version" : 5,
"_seq_no" : 6,
"_primary_term" : 1,
"found" : true,
"_source" : {
"user" : "ja",
"tool" : "ES",
"message" : "qwer"
}
},
{
"_index" : "jackey",
"_type" : "_doc",
"_id" : "2",
"_version" : 1,
"_seq_no" : 2,
"_primary_term" : 1,
"found" : true,
"_source" : {
"user" : "zhe",
"post_date" : "2019-11-15T14:12:12",
"message" : "learning Elasticsearch"
}
}
]
}
удалить документ
В операции CURD остался только один D. Давайте посмотрим, как удалить документ в ES.
Запрос на удаление указанного идентификатора используется
DELETE /<index>/_doc/<_id>
В случае большого количества параллелизма мы обычно указываем версию при удалении, чтобы определить, что удаленный документ — это тот, который мы действительно хотим удалить. Ранее мы также представили параметры запроса на удаление, которые студенты, желающие узнать больше, могут проверить непосредственно.официальная документация.
delete by query
Подобно обновлению, удаление также имеет API удаления по запросу.
POST /<index>/_delete_by_query
Также нужно сначала запросить совпадающие документы по условиям, а затем удалить эти документы. Перед выполнением запроса Elasticsearch сделает снимок указанного индекса.Если индекс изменится в процессе удаления, это вызовет конфликт операций и возвратит ошибку удаления.
Если удаленных документов много, то запрос можно выполнить и асинхронно, просто установив wait_for_completion=false.
Параметр обновления этого API отличается от параметра обновления API удаления. Параметр обновления в удалении указывает, будет ли операция видна немедленно, то есть обновляется только один сегмент, а параметр обновления в этом API должен обновить все затронутые осколки.
Bulk API
Наконец, давайте представим специальный API, API для пакетных операций. Он поддерживает два метода записи: имя индекса может быть записано в URL-адресе или в теле запроса.
-
POST /_bulk
-
POST /<index>/_bulk
В этом запросе вы можете использовать любую комбинацию предыдущих CRUD-запросов.
curl -X POST "localhost:9200/_bulk?pretty" -H 'Content-Type: application/json' -d'
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
'
Синтаксис, используемый в теле запроса, представляет собой JSON с разделителями новой строки (NDJSON). Как это использовать? Фактически, мы уже показали это в приведенном выше примере.Для таких запросов, как index или create, если сам запрос имеет тело пакета, то используется символ новой строки, чтобы указать, что следующее содержимое отделено от подзапроса, который является началом тела пакета. .
Например, запрос индекса в приведенном выше примере имеет тело пакета { "field1" : "value1" }, поэтому он появится в следующей строке запроса индекса.
Для операций пакетного выполнения сбой одной операции не повлияет на другие операции, и в конечном итоге будут возвращены результаты каждой операции.
После выполнения приведенного выше примера результат, который мы получим, должен быть
{
"took": 30,
"errors": false,
"items": [
{
"index": {
"_index": "test",
"_type": "_doc",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"status": 201,
"_seq_no" : 0,
"_primary_term": 1
}
},
{
"delete": {
"_index": "test",
"_type": "_doc",
"_id": "2",
"_version": 1,
"result": "not_found",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"status": 404,
"_seq_no" : 1,
"_primary_term" : 2
}
},
{
"create": {
"_index": "test",
"_type": "_doc",
"_id": "3",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"status": 201,
"_seq_no" : 2,
"_primary_term" : 3
}
},
{
"update": {
"_index": "test",
"_type": "_doc",
"_id": "1",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"status": 200,
"_seq_no" : 3,
"_primary_term" : 4
}
}
]
}
По сравнению с несколькими одиночными операциями выполнение пакетных операций будет иметь определенное улучшение производительности. Но в то же время есть определенные риски, поэтому при его использовании нужно быть очень осторожным.
Суммировать
В этой статье мы сначала вводим основные понятия документов и метаданных документов. Затем он знакомит с CRUD-операцией документа и Bulk API. Я полагаю, что после прочтения статьи у вас будет определенное представление о документации Elasticsearch. Затем, наконец, запустите свой Elasticsearch, а затем попробуйте эти операции самостоятельно, чтобы увидеть, что делают различные параметры запроса. Я полагаю, что после того, как вы поэкспериментируете с ними, у вас сложится более глубокое впечатление об этих API.