1. Введение в поисковый API Elasticsearch
1. Обзор поискового API
- Реализован запросный анализ данных, хранящихся в es, конечная точка — _search
- Существует две основные формы запроса
- URI Search
- Простота в эксплуатации, удобно тестировать через командную строку
- Содержит только часть синтаксиса запроса
- Request Body Search
- Полный синтаксис запроса Query DSL (Domain Specific Language), предоставляемый es
- URI Search
2. URI Search подробное объяснение и демонстрация
- Поиск осуществляется через параметр запроса url, обычно используются следующие параметры:
- q Указывает оператор запроса, синтаксис — синтаксис строки запроса.
- Поле, которое будет запрошено по умолчанию, если поле не указано в df q, если не указано, es будет запрашивать все поля
- сортировать сортировать
- тайм-аут указывает период тайм-аута, по умолчанию не тайм-аут
- форма, размер используется для подкачки
Query String Syntax
- термин и фраза
- путь альфреда эквивалентен способу альфреда ИЛИ
- "альфред уэй" словесный запрос, порядок запроса
- Пан запрос
- Альфред эквивалентен сопоставлению термина во всех полях
- указанное поле
- name:alfred
- Параметры группировки групп, используйте круглые скобки, чтобы указать правила сопоставления
- (quick OR brown) AND fox
- status:(active OR pending) title:(full text search)
PUT test_search_index
{
"settings": {
"index":{
"number_of_shards": "1"
}
}
}
POST test_search_index/doc/_bulk
{"index":{"_id":"1"}}
{"username":"alfred way","job":"java engineer","age":18,"birth":"1990-01-02","isMarried":false}
{"index":{"_id":"2"}}
{"username":"alfred","job":"java senior engineer and java specialist","age":28,"birth":"1980-05-07","isMarried":true}
{"index":{"_id":"3"}}
{"username":"lee","job":"java and ruby engineer","age":22,"birth":"1985-08-07","isMarried":false}
{"index":{"_id":"4"}}
{"username":"alfred junior way","job":"ruby engineer","age":23,"birth":"1989-08-07","isMarried":false}
- Далее мы сделаем фактический запрос.Сначала мы сделаем общий запрос.Смысл запроса в том, что все поля содержат документы Альфреда.
GET test_search_index/_search?q=alfred
{
"took" : 29,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 3,
"max_score" : 1.2039728,
"hits" : [
{
"_index" : "test_search_index",
"_type" : "doc",
"_id" : "2",
"_score" : 1.2039728,
"_source" : {
"username" : "alfred",
"job" : "java senior engineer and java specialist",
"age" : 28,
"birth" : "1980-05-07",
"isMarried" : true
}
},
{
"_index" : "test_search_index",
"_type" : "doc",
"_id" : "1",
"_score" : 0.33698124,
"_source" : {
"username" : "alfred way",
"job" : "java engineer",
"age" : 18,
"birth" : "1990-01-02",
"isMarried" : false
}
},
{
"_index" : "test_search_index",
"_type" : "doc",
"_id" : "4",
"_score" : 0.27601978,
"_source" : {
"username" : "alfred junior way",
"job" : "ruby engineer",
"age" : 23,
"birth" : "1989-08-07",
"isMarried" : false
}
}
]
}
}
- Давайте посмотрим, как es выполняет условия запроса
GET test_search_index/_search?q=alfred
{
"profile":true
}
- Запрос по полю
GET test_search_index/_search?q=username:alfred
- Просто выполните любое из условий
GET test_search_index/_search?q=username:alfred way
{
"profile":true
}
- Теперь есть два способа изменить
GET test_search_index/_search?q=username:"alfred way"
{
"profile":true
}
GET test_search_index/_search?q=username:(alfred way)
{
"profile":true
}
- логический оператор
- И(&&), ИЛИ(||), НЕ(!)
- name:(tom NOT lee)
- Обратите внимание на прописные, а не на строчные
- + - соответствуют must и must_not соответственно
- name:(tom +lee -alfred)
- + будет проанализирован как пробел в URL-адресе, можно будет использовать только результат после кодирования, то есть %2B
GET test_search_index/_search?q=username:alfred AND way
{
"profile":true
}
GET test_search_index/_search?q=username:(alfred AND way)
{
"profile":true
}
GET test_search_index/_search?q=username:(alfred NOT way)
GET test_search_index/_search?q=username:(alfred +way)
{
"profile":true
}
GET test_search_index/_search?q=username:(alfred %2Bway)
{
"profile":true
}
- Запрос диапазона, поддерживает числа и дату
- Метод записи интервала, используйте [] для закрытого интервала и {} для открытого интервала
- Арифметическая запись
GET test_search_index/_search?q=username:alfred age:>26
GET test_search_index/_search?q=username:alfred AND age:>20
GET test_search_index/_search?q=birth:(>1980 AND <1990)
- Подстановочный запрос
- ? представляет один символ, * представляет 0 или более символов
- Сопоставление с подстановочными знаками неэффективно и занимает много памяти, поэтому не рекомендуется его использовать.
- Если нет особых требований, не ставьте ?/* на первое место.
GET test_search_index/_search?q=username:alf*
- соответствие регулярному выражению
GET test_search_index/_search?q=username:/[a]?l.*/
- Нечеткий соответствующий нечеткий запрос
- name:roam~1
- Сопоставьте слова, которые отличаются от roam на 1 символ, например пена бродит и т. д.
- поиск близости
- "fox quick"~5
- Сравнение различий с точки зрения сроков
GET test_search_index/_search?q=username:alfed
GET test_search_index/_search?q=username:alfed~1
GET test_search_index/_search?q=username:alfd~2
GET test_search_index/_search?q=job:"java engineer"
GET test_search_index/_search?q=job:"java engineer"~1
GET test_search_index/_search?q=job:"java engineer"~2
3. Введение в Query DSL
- Отправьте оператор запроса в es через тело http-запроса, в основном включая следующие параметры.
- запрос — это запрос, соответствующий синтаксису Query DSL.
- форма, размер
- timeout
- sort
- ...
- Язык запросов, определенный на основе JSON, в основном включает следующие два типа:
- Запрос класса поля
- Например, термин, совпадение, диапазон и т. д., запрашивайте только определенное поле.
- Составной запрос
- Например, логический запрос и т. д., содержащий один или несколько полевых запросов или операторов составного запроса.
- Запрос класса поля
4. Введение в запрос поля и запрос соответствия
- Полевой запрос в основном включает следующие две категории:
- полное текстовое совпадение
- Для полнотекстового поиска полей текстового типа оператор запроса будет сначала сегментирован, например, match, match_phrase и другие типы запросов.
- совпадение слов
- Он не будет выполнять сегментацию слов в операторе запроса, а будет напрямую соответствовать инвертированному индексу поля, такому как термин, термины, диапазон и другие типы запросов.
- полное текстовое совпадение
GET test_search_index/_search
{
"query": {
"match": {
"username": "alfred way"
}
}
}
- Отношения соответствия между словами можно контролировать параметром оператора, варианты или и и
GET test_search_index/_search
{
"query": {
"match": {
"username": {
"query": "alfred way",
"operator": "and"
}
}
}
}
- Количество слов, которые необходимо сопоставить, можно контролировать с помощью параметра Minimum_should_match.
GET test_search_index/_search
{
"query": {
"match": {
"job": {
"query": "java ruby engineer",
"minimum_should_match": "3"
}
}
}
}
5. Оценка релевантности
- Оценка релевантности относится к степени релевантности между документом и оператором запроса, на английском языке это релевантность.
- Список документов, соответствующих запросу, можно получить с помощью инвертированного индекса, так как же поместить документы, которые лучше всего соответствуют запросам пользователя, впереди?
- Суть в задаче сортировки, а сортировка основана на показателе корреляции
- Несколько важных концепций оценки корреляции заключаются в следующем:
- Частота терминов (TF): частота слов, то есть количество раз, когда слово появляется в документе, чем выше частота слов, тем выше релевантность.
- Частота документа (DF): частота документа, т. е. количество документов, в которых встречается слово.
- Обратная частота документа (IDF): обратная частота документа, противоположная частоте документа, просто понимаемая как 1/DF, то есть чем меньше документов появляется слово, тем выше корреляция
- Норма длины поля: чем короче документ, тем выше релевантность
- В настоящее время ES в основном имеет две модели оценки корреляции, а именно:
- Модель TF/IDF
- Модель BM25: модель по умолчанию после 5.X
- Вы можете просмотреть конкретный метод расчета через параметр объяснения, но обратите внимание:
- Оценка es рассчитывается в соответствии с осколком, то есть расчет оценки осколка не зависит друг от друга, поэтому при использовании объяснения обращайте внимание на количество осколков.
- Этой проблемы можно избежать, установив количество осколков индекса равным 1.
GET test_search_index/_search
{
"explain":true,
"query": {
"match": {
"username": "alfred way"
}
}
}
- В модели BM25 BM относится к лучшему совпадению, а 25 относится к методу расчета после повторения 25 слов, что является оптимизацией для TF/IDF.
6. match-phrase-query
- Поиск полей, есть требования к порядку
GET test_search_index/_search
{
"query": {
"match_phrase": {
"job": "java engineer"
}
}
}
GET test_search_index/_search
{
"query": {
"match_phrase": {
"job": "engineer java"
}
}
}
- Интервал между словами можно контролировать с помощью параметра slop.
GET test_search_index/_search
{
"query": {
"match_phrase": {
"job": {
"query": "java engineer",
"slop": "2"
}
}
}
}
7. query-string-query
- Аналогично запросу параметра q в поиске URI
GET test_search_index/_search
{
"profile":true,
"query":{
"query_string": {
"default_field": "username",
"query": "alfred AND way"
}
}
}
GET test_search_index/_search
{
"profile":true,
"query": {
"query_string": {
"fields": [
"username",
"job"
],
"query": "alfred OR (java AND ruby)"
}
}
}
8. simple-query-string-query
- Аналогичен строке запроса, но игнорирует неправильный синтаксис запроса и поддерживает только частичный синтаксис запроса.
GET test_search_index/_search
{
"profile":true,
"query":{
"simple_query_string": {
"query": "alfred +way \"java",
"fields": ["username"]
}
}
}
GET test_search_index/_search
{
"query":{
"query_string": {
"default_field": "username",
"query": "alfred +way \"java"
}
}
}
9. term-terms-query
- Запрашивать оператор запроса как целое слово, то есть не выполнять обработку сегментации слов в операторе запроса.
GET test_search_index/_search
{
"query":{
"term":{
"username":"alfred"
}
}
}
GET test_search_index/_search
{
"query":{
"term":{
"username":"alfred way"
}
}
}
- термины: один входящий несколько запросов
G`ET test_search_index/_search
{
"query": {
"terms": {
"username": [
"alfred",
"way"
]
}
}
}
10. range-query
- Запросы диапазона в основном предназначены для числовых типов и типов даты.
GET test_search_index/_search
{
"query":{
"range": {
"age": {
"gte": 10,
"lte": 30
}
}
}
}
GET test_search_index/_search
{
"query":{
"range": {
"birth": {
"gte": "1980-01-01"
}
}
}
}
- Более удобный расчет дат
GET test_search_index/_search
{
"query":{
"range": {
"birth": {
"gte": "now-30y"
}
}
}
}
GET test_search_index/_search
{
"query":{
"range": {
"birth": {
"gte": "2010||-20y"
}
}
}
}
11. Введение в составной запрос и ConstantScore
- Составные запросы относятся к типам, которые содержат классы полей или составные запросы, включая следующие категории:
- constant_score_query
- bool query
- dis_max query
- function_score_query
- boosting query
Constant Score Query
- Запрос присваивает своей внутренней оценке документа результатов запроса значение 1 или значение boost.
- В основном используется для реализации пользовательских оценок в сочетании с логическими запросами.
GET test_search_index/_search
{
"query":{
"constant_score": {
"filter": {
"match":{
"username":"alfred"
}
}
}
}
}
GET test_search_index/_search
{
"query": {
"bool": {
"should": [
{
"constant_score": {
"filter": {
"match": {
"job": "java"
}
}
}
},
{
"constant_score": {
"filter": {
"match": {
"job": "ruby"
}
}
}
}
]
}
}
}
12. bool-query
- Логический запрос состоит из одного или нескольких логических предложений, в основном из следующих четырех:
- фильтр: фильтровать только те документы, которые соответствуют условиям, не вычислять показатель релевантности
- must: документ должен соответствовать всем условиям в must, что влияет на оценку релевантности.
- must_not: документ не должен соответствовать всем условиям в must_not
- должен: документ может соответствовать условиям в должен, что повлияет на оценку релевантности
Filter
- Запрос «Фильтр» фильтрует только те документы, которые соответствуют условиям, и не вычисляет показатель релевантности.
- es будет иметь интеллектуальный кеш для фильтра, поэтому эффективность его выполнения очень высока.
- При выполнении простого запроса на сопоставление без учета оценки рекомендуется использовать фильтр вместо запроса и т. д.
GET test_search_index/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"username": "alfred"
}
}
]
}
}
}
Must
GET test_search_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"username": "alfred"
}
},
{
"match": {
"job": "specialist"
}
}
]
}
}
}
Must_Not
GET test_search_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"job": "java"
}
}
],
"must_not": [
{
"match": {
"job": "ruby"
}
}
]
}
}
}
should
- Если документ содержит только должно, он должен соответствовать хотя бы одному условию.
- Minimum_should_match может управлять количеством или процентом выполненных условий.
GET test_search_index/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"username": "junior"
}
},
{
"match": {
"job": "ruby"
}
}
]
}
}
}
GET test_search_index/_search
{
"query": {
"bool": {
"should": [
{"term": {"job": "java"}},
{"term": {"job": "ruby"}},
{"term": {"job": "specialist"}}
],
"minimum_should_match": 2
}
}
}
- Когда включены оба параметра: must и must, документ не обязательно соответствует условиям, указанным в «должен», но если условия соблюдены, оценка релевантности будет увеличена.
GET test_search_index/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"username": "alfred"
}
}
],
"should": [
{
"term": {
"job": "ruby"
}
}
]
}
}
}
- Когда оператор запроса находится в контексте запроса или фильтра, результаты выполнения es будут другими.
- запрос: найти документ, который лучше всего соответствует формулировке запроса, оценить и отсортировать все документы по релевантности.
- фильтр: найти документы, соответствующие запросу
13. count and source filtering
- Получить количество документов, соответствующих условиям, конечная точка _count
GET test_search_index/_count
{
"query":{
"match":{
"username": "alfred"
}
}
}
source filtering
- Отфильтровать поля в _source в возвращаемом результате
GET test_search_index/_search
GET test_search_index/_search?_source=username
GET test_search_index/_search
{
"_source": false
}
GET test_search_index/_search
{
"_source": ["username","age"]
}
GET test_search_index/_search
{
"_source": {
"includes": "*i*",
"excludes": "birth"
}
}
2. Глубокое понимание механизма работы поиска в Elasticsearch.
1. Query Then Fetch
- Когда поиск выполняется, он фактически работает в два этапа.
- Этап запроса
- Стадия выборки
2. Оценка релевантности
- Оценка корреляции независима между осколками и осколками, что означает, что эквивалент IDF одного и того же термина отличается в разных осколках, а показатель корреляции документа связан с осколком, в котором он находится.
- Когда количество документов невелико, оценка корреляции будет серьезно неточной.
POST test_search_relevance/doc
{
"name":"hello"
}
POST test_search_relevance/doc
{
"name":"hello,world"
}
POST test_search_relevance/doc
{
"name":"hello,world!a beautiful world"
}
GET test_search_relevance/_search
{
"explain": true,
"query": {
"match":{
"name":"hello"
}
}
}
- Есть два пути решения проблемы:
- Во-первых, чтобы полностью устранить проблему, установите количество осколков равным 1. Это решение можно рассмотреть, когда количество документов невелико, например количество документов исчисляется миллионами или десятками миллионов.
- Второй — использовать метод запроса DFS Query-then-Fetch.
- Функция DFS Query-then-Fetch предназначена для полного пересчета оценки корреляции после получения всех документов. Она потребляет больше ресурсов ЦП и памяти, а производительность выполнения относительно низкая. Как правило, ее использовать не рекомендуется. Способ применения следующий:
GET test_search_relevance/_search?search_type=dfs_query_then_fetch
{
"query": {
"match":{
"name":"hello"
}
}
}
3. sorting doc values fielddata
- По умолчанию es будет использовать сортировку по показателю корреляции.Пользователи могут сами установить правила сортировки, задав параметр сортировки.
GET test_search_index/_search
{
"query":{
"match": {
"username": "alfred"
}
},
"sort":{
"birth":"desc"
}
}
GET test_search_index/_search
{
"query":{
"match": {
"username": "alfred"
}
},
"sort": [
{
"birth": "desc"
},
{
"_score": "desc"
},
{
"_doc": "desc"
}
]
}
- Сортировка по строкам особенная, потому что es имеет два типа: текст и ключевое слово.
- Сортировка по типу текста вызовет ошибку
- Сортировка по типу ключевого слова возвращает ожидаемый результат
GET test_search_index/_search
{
"sort":{
"username.keyword":"desc"
}
}
Сортировать
- Суть процесса сортировки заключается в процессе сортировки исходного содержимого поля, в этом процессе инвертированный индекс не может играть роли, и необходимо использовать прямой индекс, то есть исходное содержимое поля может быть быстро получить через идентификатор документа и поля.
- es предоставляет 2 способа реализовать это:
- fielddata отключен по умолчанию
- значения doc включены по умолчанию, кроме текстовых типов
Fielddata
- Полевые данные отключены по умолчанию и могут быть включены через следующие API:
- В настоящее время строки сортируются в соответствии с термином после сегментации слова, и результаты часто трудно оправдать ожидания.
- Как правило, он включается, когда анализ агрегации выполняется для сегментации слова.
PUT test_search_index/_mapping/doc
{
"properties": {
"job":{
"type":"text",
"fielddata": true
}
}
}
Doc Values
- Doc Values включены по умолчанию и могут быть отключены при создании индекса:
- Если вы хотите включить Doc Values позже, вам нужно выполнить операцию переиндексации
PUT test_doc_values/_mapping/doc
{
"properties": {
"username": {
"type": "keyword",
"doc_values": false
},
"hobby": {
"type": "keyword"
}
}
}
docvalue_fields
- Через это поле вы можете получить содержимое, хранящееся в значениях fielddata или doc.
GET test_search_index/_search
{
"docvalue_fields": [
"username",
"username.keyword",
"age"
]
}
4. Пейджинг и обход - fromsize
- es предоставляет 3 способа решения проблемы подкачки и обхода:
- from/size
- from указывает начальную позицию
- size указывает общее количество приобретений
- scoll
- search_after
- from/size
- Глубокое пейджинг — классическая проблема: как получить первую 1000 документов в случае шардированного хранилища данных?
- При получении 990~1000 документов сначала будет получено 1000 документов в каждом сегменте, затем результаты всех сегментов будут агрегированы Координационным узлом, а затем будут отсортированы и получены первые 1000 документов.
- Чем глубже количество страниц, тем больше документов обрабатывается, тем больше памяти занято и больше времени тратится, старайтесь избегать глубокого пейджинга, es ограничен 10 000 штук данных через index.max_result_window
GET test_search_index/_search
{
"from":0,
"size":2
}
GET test_search_index/_search
{
"from":10000,
"size":2
}
5. Пейджинг и обход-прокрутка
- Пройдите через API набора документов и используйте моментальный снимок, чтобы избежать проблемы глубокого пейджинга.
- Невозможно использовать для поиска в реальном времени, поскольку данные не в реальном времени.
- Старайтесь не использовать сложные условия сортировки, использование _doc является наиболее эффективным
- Это немного сложно использовать
- Первый шаг — инициировать поиск по прокрутке.
- es создает снимок коллекции идентификаторов документов в соответствии с условиями запроса после получения запроса.
GET test_search_index/_search?scroll=5m
{
"size":1 指明每次scroll返回的文档数
}
- Второй шаг вызывает API поиска прокрутки, чтобы получить коллекцию документов.
- Продолжайте повторять вызов, пока возвращаемый массив hits.hits не станет пустым, и остановитесь.
POST _search/scroll
{
"scroll" : "5m",
"scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAABswWX3FLSTZFOF9URFdqWHlvX3gtYmhtdw=="
}
- Поскольку это моментальный снимок, новые документы не могут быть получены.
PUT test_search_index/doc/10
{
"username":"doc10"
}
-
Слишком много вызовов прокрутки займут много памяти, вы можете использовать clear API, чтобы удалить слишком много снимков прокрутки.
DELETE _search/scroll/_all
6. Пейджинг и обход - search_after
- Избегайте проблем с производительностью глубокого разбиения по страницам и предоставляйте функцию поиска документов на следующей странице в реальном времени.
- Минус в том, что нельзя использовать параметр from, то есть нельзя указать количество страниц
- Только следующая страница, а не предыдущая страница
- Простой в использовании
- Первый шаг — обычный поиск, но укажите значение сортировки и убедитесь, что это значение уникально.
GET test_search_index/_search
{
"size":1,
"sort":{
"age":"desc",
"_id":"desc"
}
}
- Второй шаг — использовать значение сортировки последнего документа на предыдущем шаге для запроса.
GET test_search_index/_search
{
"size":1,
"search_after":[23,"4"],
"sort":{
"age":"desc",
"_id":"desc"
}
}
Сценарии применения
- От / размер: вам нужно получить некоторые документы вверху в режиме реального времени, и вам нужно свободно перелистывать страницы
- Прокрутка: требуется полная документация, например возможность экспорта всех данных.
- Search_After: Требуются все документы, свободное перелистывание страниц не требуется
3. Введение в анализ агрегации Elasticsearch
1. Введение в совокупный анализ
- Поисковые системы используются для ответа на такие вопросы, как:
- Подскажите, пожалуйста, все заказы с адресом в Шанхае?
- Скажите, пожалуйста, все заказы, созданные за последний 1 день, но не оплаченные?
- Агрегированный анализ может ответить на такие вопросы, как:
- Скажите, пожалуйста, какой ежедневный объем заказов за последнюю неделю?
- Скажите, пожалуйста, какая средняя сумма заказа в день за последний 1 месяц?
- Скажите, пожалуйста, какие продукты входят в топ-5 самых популярных товаров, проданных за последние шесть месяцев?
Совокупный анализ
- Агрегационный анализ, Aggregation на английском языке, — это функция, предоставляемая es для статистического анализа данных es в дополнение к функции поиска.
- Богатый функциями, он предоставляет различные методы анализа, такие как Bucket, Metric и Pipeline, которые могут удовлетворить большинство потребностей анализа.
- Высокая производительность в режиме реального времени, все результаты вычислений возвращаются вовремя, а системы больших данных, такие как Hadoop, обычно работают в режиме T+1.
Классификация
- Для простоты понимания es делит анализ агрегации на следующие четыре категории:
- Bucket, тип сегмента, аналогичный синтаксису GROUP BY в SQL.
- Метрика, тип анализа метрики, например расчет максимального значения, минимального значения, среднего значения и т. д.
- Конвейерный, тип конвейерного анализа, повторный анализ на основе агрегированных результатов анализа предыдущего уровня
- Матрица, тип матричного анализа
2. Анализ агрегации показателей
POST test_search_index/doc/_bulk
{"index":{"_id":"1"}}
{"username":"alfred way","job":"java engineer","age":18,"birth":"1990-01-02","isMarried":false,"salary":10000}
{"index":{"_id":"2"}}
{"username":"tom","job":"java senior engineer","age":28,"birth":"1980-05-07","isMarried":true,"salary":30000}
{"index":{"_id":"3"}}
{"username":"lee","job":"ruby engineer","age":22,"birth":"1985-08-07","isMarried":false,"salary":15000}
{"index":{"_id":"4"}}
{"username":"Nick","job":"web engineer","age":23,"birth":"1989-08-07","isMarried":false,"salary":8000}
{"index":{"_id":"5"}}
{"username":"Niko","job":"web engineer","age":18,"birth":"1994-08-07","isMarried":false,"salary":5000}
{"index":{"_id":"6"}}
{"username":"Michell","job":"ruby engineer","age":26,"birth":"1987-08-07","isMarried":false,"salary":12000}
- В основном делятся на следующие две категории:
- Анализ одного значения, вывод только одного результата анализа
- мин., макс., среднее, сумма
- cardinality
- Многозначный анализ, вывод нескольких результатов анализа
- статистика, предполагаемая статистика
- процентиль, процентильный ранг
- top hits
- Анализ одного значения, вывод только одного результата анализа
Min
- Возвращает минимальное значение числового поля
GET test_search_index/_search
{
"size":0,
"aggs":{
"min_age":{
"min": {
"field": "age"
}
}
}
}
Max
- Возвращает максимальное значение числового поля
GET test_search_index/_search
{
"size":0,
"aggs":{
"max_age":{
"max": {
"field": "age"
}
}
}
}
Avg
- Возвращает среднее значение числового поля
GET test_search_index/_search
{
"size":0,
"aggs":{
"avg_age":{
"avg": {
"field": "age"
}
}
}
}
Sum
- Возвращает сумму числового поля класса
GET test_search_index/_search
{
"size":0,
"aggs":{
"sum_age":{
"sum": {
"field": "age"
}
}
}
}
- Возврат нескольких агрегированных результатов одновременно
GET test_search_index/_search
{
"size": 0,
"aggs": {
"min_age": {
"min": {
"field": "age"
}
},
"max_age": {
"max": {
"field": "age"
}
},
"avg_age": {
"avg": {
"field": "age"
}
},
"sum_age": {
"sum": {
"field": "age"
}
}
}
}
Cardinality
- Кардинальность, которая означает потенциал набора или кардинальность, относится к количеству различных значений, аналогично концепции подсчета отдельных элементов в SQL.
GET test_search_index/_search
{
"size":0,
"aggs":{
"count_of_job":{
"cardinality": {
"field": "job.keyword"
}
}
}
}
Stats
- Возвращает ряд числовых статистических данных, включая минимальное, максимальное, среднее, сумму и количество
GET test_search_index/_search
{
"size":0,
"aggs":{
"stats_age":{
"stats": {
"field": "age"
}
}
}
}
Extended Stats
- Расширение для статистики, чтобы включить дополнительные статистические данные, такие как дисперсия, стандартное отклонение и т. д.
GET test_search_index/_search
{
"size":0,
"aggs":{
"exstats_salary":{
"extended_stats": {
"field": "salary"
}
}
}
}
Percentile
- Процентильная статистика
GET test_search_index/_search
{
"size":0,
"aggs":{
"per_salary":{
"percentiles": {
"field": "salary"
}
}
}
}
GET test_search_index/_search
{
"size": 0,
"aggs": {
"per_age": {
"percentiles": {
"field": "salary",
"percents": [
95,
99,
99.9
]
}
}
}
}
Percentile Rank
- Процентильная статистика
GET test_search_index/_search
{
"size": 0,
"aggs": {
"per_salary": {
"percentile_ranks": {
"field": "salary",
"values": [
11000,
30000
]
}
}
}
}
Top Hits
- Обычно он используется для получения списка наиболее подходящих документов в корзине после группировки, то есть подробных данных.
GET test_search_index/_search
{
"size": 0,
"aggs": {
"jobs": {
"terms": {
"field": "job.keyword",
"size": 10
},
"aggs": {
"top_employee": {
"top_hits": {
"size": 10,
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
}
}
}
}
}
3. Анализ агрегации ведра
- Ведро, что означает ведро, то есть назначение документов разным ведрам в соответствии с определенными правилами для достижения цели классификации и анализа.
- В соответствии со стратегией распределения корзин Bucket, общий анализ агрегации корзин выглядит следующим образом:
- Terms
- Range
- Date Range
- Histogram
- Date Histogram
Terms
- Эта стратегия группирования является самой простой, и сегменты делятся непосредственно в соответствии с термином.Если это текстовый тип, он будет разделен на сегменты в соответствии с результатом сегментации слов.
GET test_search_index/_search
{
"size": 0,
"aggs": {
"jobs": {
"terms": {
"field": "job",
"size": 5
}
}
}
}
Range
- Установите правила корзины в соответствии с указанным диапазоном значений
GET test_search_index/_search
{
"size": 0,
"aggs": {
"salary_range": {
"range": {
"field": "salary",
"ranges": [
{
"key":"<10000",
"to": 10000
},
{
"from": 10000,
"to": 20000
},
{
"key":">20000",
"from": 20000
}
]
}
}
}
}
Date Range
- Установите правила группирования, указав диапазон дат
GET test_search_index/_search
{
"size": 0,
"aggs": {
"date_range": {
"range": {
"field": "birth",
"format": "yyyy",
"ranges": [
{
"from":"1980",
"to": "1990"
},
{
"from": "1990",
"to": "2000"
},
{
"from": "2000"
}
]
}
}
}
}
Histogram
- Гистограмма, которая разбивает данные с помощью стратегии фиксированных интервалов.
GET test_search_index/_search
{
"size":0,
"aggs":{
"salary_hist":{
"histogram": {
"field": "salary",
"interval": 5000,
"extended_bounds": {
"min": 0,
"max": 40000
}
}
}
}
}
Date Histogram
- Гистограммы или гистограммы для дат являются наиболее часто используемыми типами статистического анализа при анализе данных временных рядов.
GET test_search_index/_search
{
"size":0,
"aggs":{
"by_year":{
"date_histogram": {
"field": "birth",
"interval": "year",
"format":"yyyy"
}
}
}
}
4. Сегментный и агрегированный анализ метрик
- Анализ агрегации сегментов позволяет проводить дальнейший анализ, добавляя субанализ, который может быть сегментом или метрикой, что также делает возможности агрегированного анализа чрезвычайно мощными.
- ведро за ведром
GET test_search_index/_search
{
"size": 0,
"aggs": {
"jobs": {
"terms": {
"field": "job.keyword",
"size": 10
},
"aggs": {
"age_range": {
"range": {
"field": "age",
"ranges": [
{
"to": 20
},
{
"from": 20,
"to": 30
},
{
"from": 30
}
]
}
}
}
}
}
}
- Анализ данных после группировки
GET test_search_index/_search
{
"size": 0,
"aggs": {
"jobs": {
"terms": {
"field": "job.keyword",
"size": 10
},
"aggs": {
"salary": {
"stats": {
"field": "salary"
}
}
}
}
}
}
5. Агрегационный анализ конвейера
- Результаты анализа агрегации повторно агрегируются и анализируются, а цепные вызовы поддерживаются для ответа на следующие вопросы:
- Каков средний ежемесячный объем продаж заказов?
- Результаты анализа конвейера будут выведены в исходные результаты, которые разделены на следующие две категории в зависимости от места вывода:
- Родительские результаты встроены в существующие совокупные результаты анализа
- Derivative
- Moving Average
- Cumulative Sum
- Результаты одноуровневого анализа находятся на том же уровне, что и результаты совокупного анализа.
- Max/Min/Avg/Sum Bucket
- Stats/Extended Stats Bucket
- Percentiles Bucket
- Родительские результаты встроены в существующие совокупные результаты анализа
Min Bucket
GET test_search_index/_search
{
"size":0,
"aggs":{
"jobs":{
"terms": {
"field": "job.keyword",
"size": 10
},
"aggs":{
"avg_salary":{
"avg": {
"field": "salary"
}
}
}
},
"min_salary_by_job":{
"min_bucket": {
"buckets_path": "jobs>avg_salary"
}
}
}
}
Derivative
- Вычислить производную от значения Bucket
GET test_search_index/_search
{
"size": 0,
"aggs": {
"birth": {
"date_histogram": {
"field": "birth",
"interval": "year",
"min_doc_count": 0
},
"aggs": {
"avg_salary": {
"avg": {
"field": "salary"
}
},
"derivative_avg_salary": {
"derivative": {
"buckets_path": "avg_salary"
}
}
}
}
}
}
Moving Average
- Рассчитать скользящее среднее значений корзины
Cumulative Sum
- Рассчитать совокупную сумму стоимости ведра
6. Сфера действия
- Объемом анализа агрегации es по умолчанию является набор результатов запроса, и его объем можно изменить следующими способами:
- filter
- post_filter
- global
filter
- Установите условия фильтра для совокупного анализа, тем самым изменив область действия без изменения общего оператора запроса.
GET test_search_index/_search
{
"size": 0,
"aggs": {
"jobs_salary_small": {
"filter": {
"range": {
"salary": {
"to": 10000
}
}
},
"aggs": {
"jobs": {
"terms": {
"field": "job.keyword"
}
}
}
},
"jobs": {
"terms": {
"field": "job.keyword"
}
}
}
}
post_filter
- Работает при фильтрации текста, но вступает в силу после совокупного анализа
GET test_search_index/_search
{
"aggs": {
"jobs": {
"terms": {
"field": "job.keyword"
}
}
},
"post_filter": {
"match":{
"job.keyword":"java engineer"
}
}
}
global
- Игнорировать условия фильтра запроса и анализировать на основе всех документов
GET test_search_index/_search
{
"query": {
"match": {
"job.keyword": "java engineer"
}
},
"aggs": {
"java_avg_salary": {
"avg": {
"field": "salary"
}
},
"all": {
"global": {},
"aggs": {
"avg_salary": {
"avg": {
"field": "salary"
}
}
}
}
}
}
7. Сортировка
- Вы можете использовать встроенные ключевые данные для сортировки, например:
- _count количество документов
- _key сортируется по значению ключа
GET test_search_index/_search
{
"size": 0,
"aggs": {
"jobs": {
"terms": {
"field": "job.keyword",
"size": 10,
"order": [
{
"avg_salary": "desc"
}
]
},
"aggs": {
"avg_salary": {
"avg": {
"field": "salary"
}
}
}
}
}
}
4. Моделирование данных в Elasticsearch
1. Введение в моделирование данных
- Английский — Data Modeling, то есть процесс создания модели данных.
- Модель данных
- Инструмент и метод абстрактного описания реального мира
- Бизнес-правила описываются в виде абстрактных сущностей и связей между сущностями, чтобы реализовать отображение реального мира.
процесс моделирования данных
- концептуальная модель
- Определите основные требования и границы области применения системы, сущностей проекта и взаимосвязей между сущностями.
- логическая модель
- Далее разберитесь с бизнес-требованиями и определите атрибуты, отношения и ограничения каждой сущности и т. д.
- физическая модель
- В сочетании с конкретными продуктами баз данных окончательное определение определяется исходя из требований к производительности чтения и записи и т. д.
- MySQL, MongoDB, эластичный поиск и т. д.
- третья нормальная форма
2. Введение в конфигурацию моделирования данных ES
- ES — это система хранения, реализованная на основе инвертированного индекса на основе Lucene, и не следует парадигмальным соглашениям в реляционных базах данных.
Связанные настройки поля Mapping
- enbaled
- true | false
- Только магазин, а не поиск или сводная аналитика
- index
- true | false
- нужно ли строить инвертированный индекс
- index_options
- docs | freqs | positions | offsets
- Какая информация хранится об инвертированном индексе
- norms
- true | false
- Сохранять ли параметры, связанные с нормализацией, если поле используется только для фильтрации и анализа агрегации, его можно отключить.
- doc_values
- true | false
- Включить ли doc_values для анализа сортировки и агрегации
- field_data
- false | true
- Следует ли запускать fielddata для текстового типа для реализации анализа сортировки и агрегирования
- store
- false | true
- сохранять ли значение поля
- coerce
- true | false
- Включить ли автоматическое преобразование типов данных, таких как строка в число, с плавающей запятой в целое число и т. д.
- мультиполя
- Гибкое использование многофункциональных функций для решения разнообразных бизнес-задач
- dynamic
- true | false | strict
- Управление автоматическим обновлением карт
- data_detection
- true | false
- Следует ли автоматически распознавать тип даты
Процесс установки
- Какой это тип?
- Тип строки
- тип перечисления
- Числовой тип
- другие типы
- Вам нужно искать?
- Нет необходимости извлекать, сортировать, агрегировать и анализировать поля вообще
- включено установлено значение false
- Поля, которые не нужно искать
- индекс установлен в ложь
- Для извлекаемых полей вы можете установить требуемую емкость хранилища с помощью следующей конфигурации.
- Комбинация index_options должна быть установлена
- Нормы можно отключить, если не требуются нормализованные данные.
- Нет необходимости извлекать, сортировать, агрегировать и анализировать поля вообще
- Вам нужен анализ сортировки и агрегации?
- doc_values имеет значение false
- fielddata имеет значение false
- Его нужно хранить отдельно?
- Нужно ли мне хранить данные для текущего поля специально?
3. Пример моделирования данных ES
- Сообщения в блоге blog_index
- заглавие
- дата публикацииpublish_date
- авторавтор
- Аннотация
- содержание
- URL-адрес сетевого адреса
PUT blog_index
{
"mappings": {
"doc": {
"_source": {
"enabled": false
},
"properties": {
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 100
}
},
"store": true
},
"publish_date": {
"type": "date",
"store": true
},
"author": {
"type": "keyword",
"ignore_above": 100,
"store": true
},
"abstract": {
"type": "text",
"store": true
},
"content": {
"type": "text",
"store": true
},
"url": {
"type": "keyword",
"doc_values":false,
"norms":false,
"ignore_above": 100,
"store": true
}
}
}
}
}
- Запрос
GET blog_index/_search
{
"stored_fields": ["title","publish_date","author","abstract","url"],
"query": {
"match": {
"content": "blog"
}
},
"highlight": {
"fields":{
"content": {}
}
}
}
4. Nested_Object
- ES плохо справляется с реляционными отношениями в реляционных базах данных.Например, ассоциация blog_id между таблицей article blog и комментарием в таблице комментариев может быть решена в ES в замаскированной форме следующими двумя способами.
- Nested Object
- Parent/Child
Обработка ассоциативных отношений
- Идентификатор статьи blog_id
- прокомментировал имя пользователя
- дата комментария дата
- Содержание комментария
DELETE blog_index_nested
PUT blog_index_nested
{
"mappings": {
"doc":{
"properties": {
"title":{
"type": "text",
"fields": {
"keyword":{
"type":"keyword",
"ignore_above": 100
}
}
},
"publish_date":{
"type":"date"
},
"author":{
"type":"keyword",
"ignore_above": 100
},
"abstract":{
"type": "text"
},
"url":{
"enabled":false
},
"comments":{
"type":"nested",
"properties": {
"username":{
"type":"keyword",
"ignore_above":100
},
"date":{
"type":"date"
},
"content":{
"type":"text"
}
}
}
}
}
}
}
PUT blog_index_nested/doc/2
{
"title": "Blog Number One",
"author": "alfred",
"comments": [
{
"username": "lee",
"date": "2017-01-02",
"content": "awesome article!"
},
{
"username": "fax",
"date": "2017-04-02",
"content": "thanks!"
}
]
}
GET blog_index_nested/_search
{
"query": {
"nested": {
"path": "comments",
"query": {
"bool": {
"must": [
{
"match": {
"comments.username": "lee"
}
},
{
"match": {
"comments.content": "thanks"
}
}
]
}
}
}
}
}
5. Parent_Child
- ES также предоставляет метод реализации, аналогичный соединению в реляционных базах данных, который реализуется с использованием типа данных соединения.
PUT blog_index_parent_child
{
"mappings": {
"doc": {
"properties": {
"join": {
"type": "join",
"relations": {
"blog": "comment"
}
}
}
}
}
}
PUT blog_index_parent_child/doc/1
{
"title":"blog",
"join":"blog" 指明父类型
}
PUT blog_index_parent_child/doc/2
{
"title":"blog2",
"join":"blog"
}
PUT blog_index_parent_child/doc/comment-1?routing=1 指明routing值,确保父子文档在一个分片上,一般使用父文档Id
{
"comment":"comment world",
"join":{
"name":"comment", 指明子类型
"parent":1 指明父文档Id
}
}
PUT blog_index_parent_child/doc/comment-2?routing=2
{
"comment":"comment hello",
"join":{
"name":"comment",
"parent":2
}
}
- Общие синтаксисы запросов включают следующее:
- parent_id: возвращает дочерний документ родительского документа.
- has_child: возвращает родительский документ, содержащий дочерний документ.
- has_parent: возвращает дочерний документ, содержащий родительский документ.
GET blog_index_parent_child/_search
{
"query":{
"parent_id":{
"type":"comment",
"id":"2"
}
}
}
GET blog_index_parent_child/_search
{
"query":{
"has_child": {
"type": "comment",
"query": {
"match": {
"comment": "world"
}
}
}
}
}
GET blog_index_parent_child/_search
{
"query":{
"has_parent": {
"parent_type": "blog",
"query": {
"match": {
"title": "blog"
}
}
}
}
}
6. nested_vs_parent_child
nested object
- Плюсы: документы хранятся вместе, поэтому скорость чтения высокая.
- Недостаток: при обновлении родительского или дочернего документа необходимо обновить весь документ.
- Сценарий: вложенные документы периодически обновляются, а запросы выполняются часто.
parent child
- Преимущества: родительские и дочерние документы могут обновляться независимо, не затрагивая друг друга.
- Недостатки: для поддержания отношения соединения часть памяти должна быть занята, а производительность чтения низкая.
- Сценарий: вложенные документы часто обновляются
Для решения проблемы рекомендуется выбирать максимально вложенный объект.
7. reindex
- Относится к процессу восстановления всех данных, который обычно происходит в следующих ситуациях:
- Изменения в настройках сопоставления, такие как изменения типа поля, обновления словаря токенизатора и т. д.
- Изменения в настройках индекса, такие как изменение количества осколков и т. д.
- Перенести данные
- ES предоставляет готовый API для выполнения работы.
- _update_by_query перестраивает существующий индекс
- _reindex перестраивает другие индексы
POST blog_index/_update_by_query?conflicts=proceed
POST _reindex
{
"source": {
"index": "blog_index"
},
"dest": {
"index": "blog_new_index"
}
}
- На время восстановления данных влияет размер исходного индексного документа. Чем больше размер, тем больше времени это занимает. В этом случае его нужно выполнить асинхронно, установив для параметра url wait_for_completion значение false. ES использует задачи для описать такие задачи выполнения.
POST blog_index/_update_by_query?conflicts=proceed&wait_for_completion=false
GET _tasks/_qKI6E8_TDWjXyo_x-bhmw:11996
8. Другие предложения
Версии модели данных
- Управление версиями Mapping
- Включается в код или управляется в специальном файле, добавляет комментарии и добавляется в репозитории управления версиями, такие как Git, для удобства просмотра.
- Добавьте поле метаданных для каждого и сохраните в нем некоторые метаданные, связанные с документом, чтобы упростить управление данными.
Запретить слишком много полей
- Слишком большое количество полей имеет следующие недостатки:
- Сложно поддерживать, когда есть сотни или тысячи полей, кому-то в принципе сложно четко знать значение каждого поля
- Информация о сопоставлении хранится в состоянии кластера. Слишком большое количество полей приведет к тому, что сопоставление будет слишком большим, что в конечном итоге приведет к более медленным обновлениям.
- Как правило, причина слишком большого количества полей связана с отсутствием качественного моделирования данных, например, с динамической установкой значения true.
- Рассмотрите возможность разделения нескольких индексов для решения проблемы
В конце концов
Вы можете подписаться на мою общедоступную учетную запись WeChat, чтобы учиться и развиваться вместе.