[ES от входа до реального боя] полная коллекционная версия с картой разума

Elasticsearch

在这里插入图片描述

@[toc]

Введение

elasticsearch

在这里插入图片描述

Полнотекстовый поиск является наиболее распространенным требованием, и Elasticsearch с открытым исходным кодом в настоящее время является первым выбором для полнотекстовых поисковых систем. Он может быстро хранить, искать и анализировать огромные объемы данных. Википедия, Stack Overflow, Github — все используют его. В основе Elastic лежит библиотека с открытым исходным кодом Lucene. Однако вы не можете использовать Lucene напрямую, вы должны написать свой собственный код для вызова его интерфейса. Elastic — это пакет Lucene, который предоставляет рабочий интерфейс REST API из коробки. REST API: кроссплатформенный.

1. Основные понятия

1. Индекс

Глагол, эквивалентный вставке в MySQL; существительное, эквивалентное базе данных в MySQL

2. Тип

В Index можно определить один или несколько типов; Подобно таблице в MySQL, каждый тип данных сгруппирован вместе.

3. Документ

Сохранить данные (Документ) определенного типа (Тип) под определенным индексом (Индекс), документ в формате JSON, Документ похож на содержимое таблицы в MySQL.

4. Механизм перевернутого индекса

слово записывать
красное море 1,2,3,4,5
действие 1,2,3
проводить исследования 2,5
очень 3,5
Рекорды 4
Агент 5

分词: разделить все предложение на слова

ведется учет

  • 1 - Операция Красное море
  • 2- Исследуйте операцию «Красное море»
  • 3- Специальные операции на Красном море
  • 4-Рекорды Красного моря
  • 5-Агенты Специальное исследование Красного моря

检索: 1), операция агента Красного моря? 2) Операция Красное море?

相关性得分:


2. Установка докера

1. Загрузите файл изображения

скачать эластичный поиск

docker pull elasticsearch:7.4.2 # 存储和检索数据

在这里插入图片描述

скачать кибана

docker pull kibana:7.4.2 # 可视化检索数据

在这里插入图片描述

Примечание: elasticsearch должен быть той же версии, что и kibana!

2. Создайте экземпляр

1. ElasticSearch

mkdir -p /mydata/elasticsearch/config # 在mydata文件夹下创建es的config文件夹,将docker中es的配置挂载在外部,当我们在linux虚拟机中修改es的配置文件时,就会同时修改docker中的es的配置
mkdir -p /mydata/elasticsearch/data #在mydata文件夹下创建es的data文件夹
echo "http.host:0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml # [http.host:0.0.0.0]允许任何远程机器访问es,并将其写入es的配置文件中

chmod -R 777 /mydata/elasticsearch/ # 保证权限问题

在这里插入图片描述

docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx128m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2

# docker run --name elasticsearch 创建一个es容器并起一个名字;
# -p 9200:9200 将linux的9200端口映射到docker容器的9200端口,用来给es发送http请求
# -p 9300:9300 9300是es在分布式集群状态下节点之间的通信端口  \ 换行符
# -e 指定一个参数,当前es以单节点模式运行
# *注意,ES_JAVA_OPTS非常重要,指定开发时es运行时的最小和最大内存占用为64M和128M,否则就会占用全部可用内存
# -v 挂载命令,将虚拟机中的路径和docker中的路径进行关联
# -d 后台启动服务

在这里插入图片描述

После установки elasticsearch запустим его, и найдем, что с помощьюdocker psКоманда не находит наш es при просмотре запущенного контейнера, что вызвано разрешениями текущего конфигурационного файла es, поэтому нам также необходимо модифицировать разрешения конфигурационного файла es:

[root@10 config]# cd ../
[root@10 elasticsearch]# ls
config  data  plugins
[root@10 elasticsearch]# cll
bash: cll: command not found
[root@10 elasticsearch]# ll
total 0
drwxr-xr-x. 2 root root 31 May 21 14:55 config
drwxr-xr-x. 2 root root  6 May 21 14:52 data
drwxr-xr-x. 2 root root  6 May 21 15:14 plugins
[root@10 elasticsearch]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
53c0e82ded18        redis               "docker-entrypoint.s…"   6 weeks ago         Up 4 hours          0.0.0.0:6379->6379/tcp              redis
e1c1b5a6012e        mysql:5.7           "docker-entrypoint.s…"   6 weeks ago         Up 4 hours          0.0.0.0:3306->3306/tcp, 33060/tcp   mysql
[root@10 elasticsearch]# chmod -R 777 /mydata/elasticsearch/
[root@10 elasticsearch]# ll
total 0
drwxrwxrwx. 2 root root 31 May 21 14:55 config
drwxrwxrwx. 2 root root  6 May 21 14:52 data
drwxrwxrwx. 2 root root  6 May 21 15:14 plugins

在这里插入图片描述

После изменения прав доступа к файлу мы используемdocker start elasticsearchЧтобы снова запустить es, используйтеdocker psПосле проверки команды обнаруживается, что контейнер все еще не запущен.Что это за вопрос? Мы используемdocker logs elasticsearchВзгляните на журнал запуска es:

[root@10 elasticsearch]# docker logs elasticsearch
OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
2020-05-21 15:14:13,179 main ERROR No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2
Exception in thread "main" SettingsException[Failed to load settings from [elasticsearch.yml]]; nested: ParsingException[Failed to parse object: expecting token of type [START_OBJECT] but found [VALUE_STRING]];
        at org.elasticsearch.common.settings.Settings$Builder.loadFromStream(Settings.java:1097)
        at org.elasticsearch.common.settings.Settings$Builder.loadFromPath(Settings.java:1070)
        at org.elasticsearch.node.InternalSettingsPreparer.prepareEnvironment(InternalSettingsPreparer.java:83)
        at org.elasticsearch.cli.EnvironmentAwareCommand.createEnv(EnvironmentAwareCommand.java:95)
        at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86)
        at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:125)
        at org.elasticsearch.cli.Command.main(Command.java:90)
        at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:115)
        at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92)
Caused by: ParsingException[Failed to parse object: expecting token of type [START_OBJECT] but found [VALUE_STRING]]
        at org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken(XContentParserUtils.java:78)
        at org.elasticsearch.common.settings.Settings.fromXContent(Settings.java:617)
        at org.elasticsearch.common.settings.Settings.access$400(Settings.java:82)

Вышеупомянутая ошибка связана с моей предыдущей конфигурациейelasticsearch.ymlПара ключ-значение k-v неправильно настроена в файле.Посмотрев файл yml, вы обнаружите, что содержимое моей конфигурации выглядит следующим образом:

http.host:0.0.0.0

На самом деле между парами ключ-значение k-v должны быть пробелы, обратите внимание на формат ключ: значение в конфигурационном файле yml冒号за которым следует空格. В противном случае возникнет указанная выше ошибка. Значит надо модифицироватьelasticsearch.ymlфайл, измененный на:

http.host: 0.0.0.0

Измените и сохраните и используйте сноваdocker start elasticsearchчтобы начать es, используйтеdocker psПосле просмотра команды видно, что мой контейнер es запущен:

在这里插入图片描述

Доступ в адресной строке браузераhttp://192.168.56.10:9200/, вы можете видеть, что es возвращает данные, подобные следующим, после успешного запуска:

在这里插入图片描述

Уведомление192.168.56.10это адрес моей виртуальной машины Linux, читатели должны получить доступ в соответствии с адресом своей виртуальной машины

2, Kibana

Установить визуальный интерфейс

docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.56.10:9200 -p 5601:5601 \
-d kibana:7.4.2

Обратите внимание, обязательно192.168.56.10Измените его на свой собственный адрес виртуальной машины.

在这里插入图片描述

После завершения установки зайдите в адресную строку браузераhttp://192.168.56.10:5601/, вы можете видеть, что кибана успешно запущена:

在这里插入图片描述

Вы можете выбрать да или нет:

在这里插入图片描述

Используя наши собственные данные:

在这里插入图片描述

Интерфейс успешной установки:

在这里插入图片描述

Примечание: при посещенииhttp://192.168.56.10:5601/Когда появится следующее приглашение, вы можете подождать некоторое время, возможно, кибана не была успешно запущена.

在这里插入图片描述

также можно использоватьdocker logs kibanaДавайте посмотрим на журнал запуска кибаны, Следующий журнал показывает, что кибана запускается нормально:

在这里插入图片描述


3. Предварительный поиск

Все запросы к ES инкапсулированы как REST API, поэтому мы можем использовать postman для доступа к нему.

Используйте почтальон или введите путь запроса в адресной строке браузераhttp://192.168.56.10:9200/_cat/xxx

1. _кот

  • GET /_cat/nodes: просмотреть все узлы

/_cat/nodes

  • GET /_cat/health: просмотреть состояние работоспособности es

/_cat/health

  • GET /_cat/master: просмотреть главный узел

/_cat/master

  • GET /_cat/indices: просмотреть все индексы; эквивалентно MySQLshow databases;

/_cat/indices

2. Индексировать документ (соответствует Mysql для сохранения записи)

Сохранить данные, где их сохранить索引какой из类型затем укажите, какой уникальный идентификатор использоватьPUT customer/external/1; Сохраните данные № 1 во внешнем типе под индексом клиента как

PUT customer/external/1
{
"name":"lohn Doe"
}
PUTиPOSTВсе будет хорошо;
POSTДобавлен. Если идентификатор не указан, идентификатор будет сгенерирован автоматически. Указание идентификатора изменит данные и добавит номер версии;
PUTЕго можно добавить или изменить. PUT должен указывать идентификатор, поскольку PUT должен указывать идентификатор, мы обычно используем его для модификации;

Введите в адресную строку почтальонаhttp://192.168.56.10:9200/customer/external/1, используя метод put, введите тело параметра:

{
"name":"lohn Doe"
}

Вы можете видеть, что запись была успешно создана:

在这里插入图片描述

После повторной отправки запроса я получаю следующий результат:

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 2, //注意版本号
    "result": "updated",//注意结果是 update
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 1, //注意序列号
    "_primary_term": 1
}

Таким образом, метод put можно использовать для добавления или обновления.

Отправить с помощью почтового метода в почтальонеhttp://192.168.56.10:9200/customer/external/Request, обратите внимание, что id отсутствует, а используются параметры в методе put выше. Вы можете видеть, что запись была создана успешно, и es помог нам сгенерировать идентификатор:

在这里插入图片描述
Когда мы отправляем другой почтовый запрос с этим идентификатором, он становится операцией обновления:
在这里插入图片描述
Таким образом, когда метод post не имеет идентификатора, это новое дополнение, когда идентификатор не существует, это также новое дополнение, когда идентификатор существует и данные существуют, это операция обновления.

Итак, вопрос в том, в чем разница между методами put и post? Разве это не сработает, если вы используете метод put для отправки запроса без идентификатора?

在这里插入图片描述
Видно, что использование метода put без запроса id сообщит об ошибке, то есть put не разрешен запрос без id, а post разрешен.

3. Запросить документы

3.1, получить данные запроса

GET customer/external/1
результат:
{
"_index": "клиент", // по какому индексу
"_type": "внешний", //в каком типе
"_id": "1", // идентификатор записи
"_version": 4, //номер версии
"_seq_no": 5, // Поле управления параллелизмом, каждое обновление будет +1, используется для оптимистичной блокировки
"_primary_term": 1, // То же, что и выше, первичный осколок переназначается, при перезапуске он изменится
"found": true, //указывает, что данные найдены
"_source": { //Содержимое данных
"name": "lohn Doe"
}
}
Обновление содержит ?if_seq_no=0&if_primary_term=1

Запрос с использованием метода get в почтальонеhttp://192.168.56.10:9200/customer/external/1, вы получите следующий результат:

{
    "_index": "customer",	//在哪个索引
    "_type": "external",	//在哪个类型
    "_id": "1",				//记录id
    "_version": 4,			//版本号
    "_seq_no": 5,			//并发控制字段,每次更新就会+1,用来做乐观锁
    "_primary_term": 1,		//同上,主分片重新分配,如重启,就会变化
    "found": true,			//表示找到了数据
    "_source": {			//数据内容
        "name": "lohn Doe"
    }
}

3.2, оптимистичная модификация замка

Чтобы использовать оптимистическую модификацию блокировки, нам нужно добавить к пути запроса на размещение или публикацию?if_seq_no=0&if_primary_term=1поле; Мы используем метод put в почтальоне для отправкиhttp://192.168.56.10:9200/customer/external/1?if_seq_no=0&if_primary_term=1запрос, параметр

{
"name":"update"
}

После выполнения операции ошибки обновления появляются следующие возвращаемые результаты:

在这里插入图片描述

Если мы используем последний серийный номер для обновления, он вернет успешное обновление со статусом 200:

在这里插入图片描述

4. Обновление документации

операция обновления аргумент или заключение
POST
customer/external/1/_update
{
"doc": {
"name": "Jane Doe",
"age": 20
}
}
или ОТПРАВИТЬ
customer/external/1
{
"name": "John Nash2"
}
или ПОСТАВИТЬ
customer/external/1
{
"name": "John Nash3"
}
разные Операция POST будет сравнивать данные исходного документа, если они совпадают, операции не будет, а версия документа и _seq_no не будут увеличиваться;
Операция PUT всегда сохраняет данные и увеличивает версию;
Сравните метаданные с _update и ничего не делайте, если они совпадают.
увидеть сцену Для больших одновременных обновлений без обновления;
Периодические обновления для больших одновременных запросов с обновлением; по сравнению с обновлениями пересчитать правила распределения.
Обновите и добавьте атрибуты
POST
customer/external/1/_update
{
"doc": {
"name": "Jane Doe",
"age": 20
}
}
Обновите и добавьте атрибуты
PUT&POST
customer/external/1
{
"name": "John Nash2",
"age": 40
}

использовать ремень_updateПочтовый запрос обновляет данные, которые отправляются с помощью метода post в почтальоне.http://192.168.56.10:9200/customer/external/1/_updateЗапрос, передача параметров:

{
     "doc": {
          "name": "John Nash"
     }
}

Отправка запроса может привести к следующим результатам, и вы увидите, что обновление прошло успешно:

在这里插入图片描述
Отправьте запрос еще раз, вы можете увидеть, что если данные совпадают, сравните исходные данные и ничего не делайте так же, как оригинал,_version,_seq_noИ не изменится:
在这里插入图片描述

использоватьпояс_updateПочтовый запрос обновляет данные, которые отправляются с помощью метода post в почтальоне.http://192.168.56.10:9200/customer/external/1просить, Параметры такие же, как и выше, вы видите, что данные будут обновляться каждый раз, когда вы нажимаете, и данные не будут проверены:

在这里插入图片描述

Обратите внимание, что для обновлений без _update вы можете использовать

{
     "doc": {
          "name": "John Nash",
          "age":40
     }
}

Также можно использовать:

{
     "name": "John Nash2",
     "age": 40
}

5. Удалить документы и индексы

удалить тип метод или параметр пути
удалить документ DELETE customer/external/1
падение индекса DELETE customer

5.1, удалить документы

Отправить с помощью метода удаления в почтальонеhttp://192.168.56.10:9200/customer/external/1Запрос, вы можете увидеть следующие результаты, вы можете видеть, что удаление документа прошло успешно:

在这里插入图片描述

Повторная отправка запроса вернет статус 404.not_foundрезультат:

在这里插入图片描述

Запрос только что удаленного документа вернет"found": falseРезультат статуса 404:

在这里插入图片描述

5.2, удалить индекс

Отправить с помощью метода удаления в почтальонеhttp://192.168.56.10:9200/customerЗапрос, вы можете увидеть следующие результаты, вы можете видеть, что удаление индекса прошло успешно:

在这里插入图片描述

Повторная отправка запроса вернет статус 404.index_not_found_exceptionрезультат:

在这里插入图片描述

Запрос индекса, который вы только что удалили, вернетno such index [customer]Результат статуса 404:

在这里插入图片描述

Тогда возникает проблема, так как его можно удалить文档и索引, тогда можно удалить类型Шерстяная ткань?

В ES есть много типов под индексом, но ES не предоставляет метод для удаления типов.Если индекс будет удален, все типы будут удалены.

6. Массовый пакетный API

действовать параметр
POST
customer/external/_bulk
{"index" {"_id":"1"}
{"name": "John Nash"}

{"index":"_id"2"}
{"name": "Jane Nash"}
формат синтаксиса {action: {metadata}}\n
{request body}\n

{action: {metadata}}\n
{request body}\n
сложный экземпляр
POST /_bulk
{"delete":{"_index":"website","_type":"blog","_id":"123"}}
{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title":"My first blog post"}
{"index":{"_index":"website","_type":"blog"}}
{"title":"My second blog post"}
{"update":{"_index":"website","_type":"blog","_id":"123"}}
{"doc":{"title":"My updated blog post"}}

Чтобы использовать массовый пакетный API, нам нужно выполнить наши операции в кибане, Если запрос будет сделан в почтальоне, будет сообщено об ошибке: Прежде всего, данные в нашем теле запроса больше не в формате json, мы используем текстовый формат, и будет сообщено о следующей ошибке:

在这里插入图片描述

Попробуем еще раз с json:

在这里插入图片描述
Приведенный выше формат json неверен, измените его и повторите попытку:
在这里插入图片描述
Видно, что массовые пакетные операции не могут быть выполнены в postman, нам нужно работать в ранее установленной кибане. Откройте консоль kibana и выберитеDevTools:
在这里插入图片描述

Появляется после нажатияDevToolsИнтерфейс работы с данными. Мы здесь, чтобы выполнять манипуляции с данными:

在这里插入图片描述

использоватьDevToolsДля выполнения пакетной операции вы можете увидеть следующие результаты:

在这里插入图片描述

Выполните сложную пакетную операцию:

POST /_bulk
{"delete":{"_index":"website","_type":"blog","_id":"123"}}
{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title":"My first blog post"}
{"index":{"_index":"website","_type":"blog"}}
{"title":"My second blog post"}
{"update":{"_index":"website","_type":"blog","_id":"123"}}
{"doc":{"title":"My updated blog post"}}

используется непосредственно над/_bulk, не указывает конкретный индекс, указывая на то, что он выполняется глобально в ES. Результат выполнения следующий:

在这里插入图片描述

Массовый API выполняет все в этом порядкеaction(действие). Если одно действие по какой-либо причине не удается, оно продолжит обработку остальных действий, следующих за ним. Когда массовый API вернется, он предоставит статус каждого действия (в том же порядке, в котором оно было отправлено), чтобы вы могли проверить, не завершилось ли данное действие ошибкой.

7. Образец тестовых данных

Я подготовил образец фиктивного документа JSON с информацией о банковском счете клиента. Каждый документ имеет следующую схему:

schema
{
"account_number": 1,
"balance": 39225,
"firstname": "Amber",
"lastname": "Duke",
"age": 32,
"gender": "M",
"address": "880 Holmes Lane",
"employer": "Pyrami",
"email": "amberduke@pyrami.com",
"city": "Brogan",
"state": "IL"
}

Приведенные выше данные взяты из официальной документации ES на github, доступ к которой можно получить по следующему адресу:

accounts.jsonИмпорт тестовых данных

Выполнить тестовые данные в ESPOST bank/account/_bulk:

在这里插入图片描述

Если сложно скопировать данные на github, можно использовать данные, которые я скачал:accounts.json, или посетитеgitee-accounts.json

Можно использовать после созданияhttp://192.168.56.10:9200/_cat/indices, чтобы посмотреть на индекс в ES сейчас, вы можете увидеть, что индекс с банком имеет 1000 единиц данных:

在这里插入图片描述


4. Расширенный поиск

1. ПоискAPl

ES поддерживает два основных способа получения:

  • Один с помощьюREST request URIОтправить параметры поиска (uri+检索参数)
  • Другой - с помощьюREST requestbodyотправить их(uri+请求体)

1), получить информацию

Все поиски начинаются с _searchuri+检索参数:

запросить или вернуть объяснять
GET bank/_search Получить всю информацию о банке, включая тип и документы
GET bank/_search?q=*&sort=account_number:asc Получение метода параметра запроса
Интерпретация результата ответа:
took Время, затраченное Elasticsearch на поиск (в секундах)
time_out Сообщите нам, если время поиска истекло
_shards Сообщает нам, сколько осколков было обыскано, и подсчитывает осколки успешного/неудачного поиска.
hits результаты поиска
hits.total результаты поиска
hits.hits массив фактических результатов поиска (по умолчанию 10 лучших документов)
sort Ключ результата сортировки (ключ) (если не отсортирован по баллам)
оценка и max_score Оценка релевантности и высшая оценка (для полнотекстового поиска)

результат поиска:

在这里插入图片描述

uri+请求体 进行检索:

uri+请求体 进行检索
GET /bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"account_number": "asc"
},
{
"balance": "desc"
}
]
}
HTTP-клиент (POSTMAN), запрос на получение не может содержать тело запроса, и то же самое верно, когда мы переходим на публикацию.Мы отправляем тело запроса в стиле JSON в _search APl.
Следует понимать, что после возврата результатов поиска Elasticsearch завершает запрос и не поддерживает какие-либо серверные ресурсы или курсоры результатов (курсоры).

результат поиска:

在这里插入图片描述

Справочная документация

2. Запрос DSL

используется в предыдущем разделе формы

GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": "asc"
    },
    {
      "balance": "desc"
    }
  ]
}

стиль языка запросов, который мы называемQuery DSL.

1), основной формат грамматики

Elastisearch предоставляет DSl в стиле Json (предметно-ориентированный язык), который может выполнять запросы. Это называется Query DSL. Язык запросов очень всеобъемлющий и поначалу кажется немного сложным, но чтобы по-настоящему хорошо его изучить, нужно начать с нескольких простых примеров.

  • Типичная структура оператора запроса

2. Запрос DSL

используется в предыдущем разделе формы

GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": "asc"
    },
    {
      "balance": "desc"
    }
  ]
}

стиль языка запросов, который мы называемQuery DSL.

1), основной формат грамматики

Elastisearch предоставляет DSl в стиле Json (предметно-ориентированный язык), который может выполнять запросы. Это называется Query DSL. Язык запросов очень всеобъемлющий и поначалу кажется немного сложным, но чтобы по-настоящему хорошо его изучить, нужно начать с нескольких простых примеров.

  • Типичная структура оператора запроса
{
	QUERY_NAME:{
		ARGUMENT: VALUE,
		ARGUMENT: VALUE,
		...
	}
}

Например:

GET /bank/_search
{
  "query": {
    "match_all": {}
  }
}

在这里插入图片描述

  • Если он для поля, то его структура следующая:
{
	QUERY_NAME:{
		FIELD_NAME:{
			ARGUMENT: VALUE,
			ARGUMENT: VALUE,
			...
		}
	}
}

Например:

GET /bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"balance": {
"order": "desc"
}
}
],
"from": 0,
"size": 5
}
- запрос определяет, как запрашивать;
- Тип запроса match_all [представляет все запросы], в es вы можете комбинировать множество типов запросов в запросе для выполнения сложных запросов.
- В дополнение к параметру запроса мы также можем передать другие параметры, чтобы изменить результат запроса. Такие, как сортировка, размер;
- from+size ограничен для выполнения функции подкачки;
- сортировка сортировки, сортировка по нескольким полям, последующие поля будут сортироваться внутри, когда предыдущие поля равны, в противном случае преобладает предыдущий порядок

在这里插入图片描述

2), вернуть некоторые поля

GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "balance": {
        "order": "desc"
      }
    }
  ],
  "from": 0,
  "size": 5,
  "_source": ["balance","firstname"]
}

просто вернись_sourceПоля, указанные в , аналогичны полям в MySQL.select field_1,field_2,... from table

在这里插入图片描述

Справочная документация-запрос-dsl

3), сопоставить [сопоставить запрос]

  • Примитивный тип (не строка), точное совпадение

match возвращает данные с account_number=20:

GET /bank/_search
{
  "query": {
    "match": {
      "account_number": 20
    }
  }
}

在这里插入图片描述

  • Строка, полнотекстовый поиск

Наконец, запрашиваются все записи, содержащие в адресе слово Kings.При поиске строковых типов будет выполняться полнотекстовый поиск, и каждая запись имеет показатель релевантности.

GET /bank/_search
{
  "query": {
    "match": {
      "address": "Kings"
    }
  }
}

在这里插入图片描述

  • Строка, несколько слов (сегментация слов + полнотекстовый поиск)

Полнотекстовый поиск сортируется в соответствии с оценкой, а критерии поиска будут соответствовать сегментации слов.

GET /bank/_search
{
  "query": {
    "match": {
      "address": "Mill Lane"
    }
  }
}

Наконец, запрашиваются все записи, содержащие в адресе Mill, Lane или Mill Lane, и выдается оценка корреляции.

在这里插入图片描述

Справочная документация-запрос-dsl

4), match_phrase [фразовое соответствие]

Получить значение для сопоставления как целое слово (без сегментации слов)

Например: узнать, что адрес содержитmill roadВсе записи и дать оценку релевантности

GET /bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill road"
    }
  }
}

在这里插入图片描述

Справочная документация-запрос-dsl

5), multi_match [совпадение нескольких полей]

Пример: состояние или адрес содержит мельницу

GET /bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill",
      "fields": ["address","state"]
    }
  }
}

在这里插入图片描述

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

GET /bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill movico",
      "fields": ["address","city"]
    }
  }
}

在这里插入图片描述

Справочная документация-запрос-dsl

6), bool [составной запрос]

bool используется для создания составных запросов:

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

  • must: все условия, перечисленные в must, должны быть соблюдены
GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "gender": "F"
          }
        },
        {
          "match": {
            "address": "Mill"
          }
        }
      ]
    }
  }
}

在这里插入图片描述

  • must_not: предложение (запрос) не должно появляться в соответствующих документах.
GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "gender": "F"
          }
        },
        {
          "match": {
            "address": "Mill"
          }
        }
      ],
      "must_not": [
        {"match": {
          "age": 30
        }}
      ]
    }
  }
}

在这里插入图片描述

  • должен: Предложение (запрос) должно появиться в соответствующих документах. (должен означает, что лучше иметь, а можно и не иметь)
GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "gender": "M"
          }
        },
        {
          "match": {
            "address": "Mill"
          }
        }
      ],
      "must_not": [
        {"match": {
          "age": 30
        }}
      ],
      "should": [
        {"match": {
          "lastname": "Holland"
        }}
      ]
    }
  }
}

在这里插入图片描述

логический запрос

Запросы, соответствующие документам, которые соответствуют логическим комбинациям других запросов. Логический запрос, сопоставленный с LuceneBooleanQuery. Он создается с использованием одного или нескольких логических предложений, каждое из которых имеет вхождение определенного типа. Тип возникновения:

происходить описывать
must Условие (запрос) должно появиться в соответствующих документах и ​​будет способствовать подсчету баллов.
filter Предложение (запрос) должно появиться в соответствующем документе. но не нравитсяmustОценки запросов будут игнорироваться. Предложение фильтра вконтекст фильтра, что означает, что оценка игнорируется, а предложение рассматривается для кэширования.
should Пункт (запрос) должен появиться в соответствующих документах.
must_not Пункт (запрос) не должен появляться в соответствующих документах. оговорка вконтекст фильтравыполняется в , что означает, что оценка игнорируется, а предложение рассматривается для кэширования. Из-за игнорирования баллов,0Таким образом, баллы за все документы будут возвращены.

Справочная документация-запрос-dsl-bool-запрос

Давайте посмотрим в следующем разделеfilterФильтрация результатов.

Справочная документация-запрос-dsl

7), фильтр [результат фильтрации]

Не все запросы должны давать оценки, особенно те, которые используются только для «подгонки» (фильтрации) документов. Чтобы не подсчитывать баллы, Elasticsearch автоматически проверит сцену и оптимизирует выполнение запроса. Запрос, указанный под элементом фильтра, не влияет на оценку — оценка возвращается как 0. На оценки влияет только указанный запрос. отmustПример запроса:

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {"range": {
          "age": {
            "gte": 18,
            "lte": 30
          }
        }}
      ]
    }
  }
}

在这里插入图片描述

использоватьfilterзаменитьmustзапрос, следует отметить, что использованиеfilterрезультаты запроса иmustРезультаты запроса непротиворечивы, разница лишь в том, что нет оценки корреляции:

GET /bank/_search
{
  "query": {
    "bool": {
      "filter": {
        "range": {
          "age": {
            "gte": 18,
            "lte": 30
          }
        }
      }
    }
  }
}

在这里插入图片描述

по этому мыshouldможно добавить позжеfilterФильтровать по условию:

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "gender": "M"
          }
        },
        {
          "match": {
            "address": "Mill"
          }
        }
      ],
      "must_not": [
        {"match": {
          "age": 30
        }}
      ],
      "should": [
        {"match": {
          "lastname": "Holland"
        }}
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 18,
            "lte": 30
          }
        }
      }
    }
  }
}

在这里插入图片描述

Справочная документация-запрос-dsl

8), срок

То же, что матч. Соответствует значению атрибута.全文检索字段用 match,其他非 text 字段匹配用 term.

Avoid using the term query for text fields.

By default, Elasticsearch changes the values of text fields as part of analysis. This can make finding exact matches for text field values difficult.

To search text field values, use the match query instead.

Нетекстовые значения извлекаются с помощью term:

GET /bank/_search
{
  "query": {
    "term": {
      "age":28
    }
  }
}

在这里插入图片描述

соответствоватьxxx.keyword, поиск точного совпадения текста:

GET /bank/_search
{
  "query": {
    "match": {
      "address.keyword": "789 Madison"
    }
  }
}

在这里插入图片描述

match Сопоставление полнотекстовой сегментации слов:

GET /bank/_search
{
  "query": {
    "match": {
      "address": "789 Madison"
    }
  }
}

在这里插入图片描述

match_phrase, извлекает значение для сопоставления как целое слово (без сегментации слов):

GET /bank/_search
{
  "query": {
    "match_phrase": {
      "address": "789 Madison"
    }
  }
}

在这里插入图片描述

注意: если термин используется для извлечения текстовых значений, он будет выполнять не сегментацию слов, а точный поиск, поэтому он может не соответствовать данным:

GET /bank/_search
{
  "query": {
    "term": {
      "address": "789 Madison"
    }
  }
}

在这里插入图片描述

Справочная документация-запрос-dsl-term-запрос Справочная документация-запрос-dsl

9) , агрегации (выполнить агрегацию)

Агрегация предоставляет данные из分组和提取数据Способность. Простейший метод агрегации примерно равенSQL GROUP BYиSQL 聚合函数. В Elasticsearch вы выполняете поиск, который одновременно возвращает совпадения и сводные результаты. Возможность выделить все попадания в ответ. Это очень мощно и эффективно, вы можете выполнять запросы и множественные агрегации, И получить их соответствующие (любые) результаты возврата за одно использование, используя чистый и упрощенный API, чтобы избежать обмена данными по сети.

Синтаксис запроса агрегации:

"aggregations" : {
    "<aggregation_name>" : {
        "<aggregation_type>" : {
            <aggregation_body>
        }
        [,"meta" : {  [<meta_data_body>] } ]?
        [,"aggregations" : { [<sub_aggregation>]+ } ]?
    }
    [,"<aggregation_name_2>" : { ... } ]*
}

Возьмите каштан:

  • Выполняет поиск распределения по возрасту и среднего возраста всех людей, чей адрес содержит слово «mill», но не отображает сведения об этих людях.
GET /bank/_search
{
  "query": { //查询
    "match": {
      "address": "mill"
    }
  },
  "aggs": { //聚合
    "ageAgg": { //年龄分布
      "terms": {
        "field": "age",
        "size": 10 //只取10中聚合的结果
      }
    },
    "ageAvg":{//平均年龄,基于上一次的结果
      "avg": {
        "field": "age"
      }
    },
    "balanceAvg":{//平均薪资
      "avg": {
        "field": "balance"
      }
    }
  },
  "size": 0 //不显示搜索数据,只显示聚合结果
}

在这里插入图片描述

aggs,执行聚合。聚合语法如下:
"aggs":{
	"ages_name 这次聚合的名字,方便展示在结果集中":{
		"AGG-TYPE 聚合的类型(avg,term,terms) ":{}
	}
}
  • Сложная агрегация: агрегируйте по возрасту и запросите среднюю зарплату этих людей в этих возрастных группах (используя субагрегацию).
GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {//年龄范围分布聚合
        "field": "age",
        "size": 100//返回100中情况
      },
      "aggs": {//基于ageAgg的结果做聚合
        "ageAvg": {
          "avg": {//求balance的平均值
            "field": "balance"
          }
        }
      }
    }
  }
}

在这里插入图片描述

  • Расширенное сложное агрегирование: найдите все распределения по возрасту, а также среднюю заработную плату M и F в этих возрастных группах и общую среднюю новую заработную плату в этой возрастной группе.
GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {//聚合
    "ageAgg":{
      "terms": {//年龄分布
        "field": "age",
        "size": 100
      },
      "aggs": {//基于ageAgg做聚合
        "genderAgg": {//性别分布
          "terms": {
            //文本字段聚合使用keyword进行精确匹配,否则会报错
            "field": "gender.keyword",
            "size": 10
          },
          "aggs": {//基于genderAgg做聚合
            "balanceAvg": {//求性别为M和F的各自的平均薪资
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "ageBalanceAvg":{//基于ageAgg,求各个年龄段的平均薪资
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

在这里插入图片描述

Дополнительные сведения об операциях запроса агрегации см. в официальной документации ES:Справочная документация-поиск-агрегации

Справочная документация-запрос-dsl

3. Отображение

1), тип поля

  • основной тип

    • строка (строка)text,keyword
    • Числовой типlong, integer, short, byte, double, float, half_float, scaled_float
    • Тип даты (Дата)date
    • Логический тип (Boolean)boolean
    • Двоичный тип (Двоичный)binary
  • составной тип

    • Тип массива (массив)ArrayПоддержка не предназначена для конкретных типов данных
    • Тип объекта (Объект)objectобъект для одного объекта JSON
    • ВложенныйnestedМассив для объектов JSON
  • Географический тип (гео)

    • Гео-точкаgeo_pointКоординаты широты/долготы
    • Геоформаgeo_shapeДля сложных форм, таких как многоугольники
  • конкретный тип

    • Тип IP (IP)ipИспользуется для описания адресов IPv4 и IPv6.
    • ЗавершениеcompletionПредоставляет подсказки автозаполнения
    • Тип счетчика токеновtoken_countИспользуется для подсчета количества терминов в строке
    • тип вложения Ссылаться наmapper-attachmentsПлагин, который поддерживает индексирование вложений, таких как формат Microsoft Office, формат открытого документа, ePub, HTML и т. д.attachmentтип данных.
    • Тип экстракции (перколятор) Принимает данные из доменных языков (query-dsl) запрос

Дополнительные типы полей см. в официальной документации ES:Справочная документация-сопоставление-типы

2), отображение

ОтображениеMapping 是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的. Например, используя сопоставление для определения:

  • Какие строковые свойства следует считать полнотекстовыми полями

  • Какие свойства содержат числа, даты или географические местоположения

  • Можно ли индексировать все атрибуты в документе (конфигурация _all)

  • Формат даты

  • Пользовательские правила сопоставления для динамического добавления свойств

  • Просмотр информации о сопоставлении:GET bank/_mapping

    在这里插入图片描述

  • Измените информацию о сопоставлении:

    • создать индекс
PUT /my-index
{
  "mappings": {//映射规则
    "properties": {
      "age":    { "type": "integer" },  
      "email":  { "type": "keyword"  },//keyword不会进行全文检索 
      "name":   { "type": "text"  }//text保存的时候进行分词,搜索的时候进行全文检索   
    }
  }
}

在这里插入图片描述
Тип отображения, который ES автоматически угадывает:

JSON type Тип домена
Логическое значение: истина, ложь boolean
Целое число: 123 long
поплавок: 1,23 double
Строка, дата действия 2020-02-02 date
строка, фу бар string
Объекты, также известные как хэши, хранят типы объектов. object

Справочная документация-сопоставление

3), новая версия меняется

ES7 и выше удалили концепцию типа.

  • В реляционных базах данных два представления данных независимы, даже если в них есть столбцы с одинаковым именем, это не влияет на использование, но в ES это не так. Elasticsearch — это поисковая система, разработанная на основе Lucene, и файлы с одинаковыми именами и разными типами в ES в конечном итоге обрабатываются в Lucene одинаково.
    • Два имени пользователя в двух разных типах на самом деле считаются одним и тем же файлом с одним и тем же индексом ES.Вы должны определить одно и то же сопоставление файлов в двух разных типах. В противном случае одни и те же имена полей в разных типах будут конфликтовать при обработке, что приведет к снижению эффективности обработки Lucene.
    • Удаление type необходимо для повышения эффективности обработки данных ES.

Эластичный поиск 7.x:

  • Параметр типа в URL является необязательным. Например, для индексирования документа больше не требуется тип документа.

Эластичный поиск 8.x:

  • Параметр type в URL больше не поддерживается.

解决: 1) Перенести индекс с многотипного на однотипный с независимым индексом для каждого типа документа. 2) Перенести все данные типа из существующего индекса в указанное место. Подробности см. в разделе перенос данных.

1. Создайте карту

Создайте индекс и укажите сопоставление

PUT /my-index
{
  "mappings": {//映射规则
    "properties": {
      "age":    { "type": "integer" },  
      "email":  { "type": "keyword"  },//keyword不会进行全文检索 
      "name":   { "type": "text"  }//text保存的时候进行分词,搜索的时候进行全文检索   
    }
  }
}

在这里插入图片描述

2. Добавьте новое сопоставление полей

PUT /my-index/_mapping
{
  "properties": {
    "employee-id": {
      "type": "keyword",
      "index": false//索引选项控制是否对字段值建立索引。 它接受true或false,默认为true。未索引的字段不可查询。
    }
  }
}

在这里插入图片描述

3. Обновите сопоставление

Мы не можем обновить существующие сопоставленные поля. Обновления должны создавать новые индексы для переноса данных.

Справочная документация-сопоставление

4. Миграция данных

Сначала создайте правильное сопоставление для Twitter. Затем используйте следующие методы для переноса данных

# 7.x 之后的写法
POST _reindex	//固定写法
{
  "source": {	//老索引
    "index": "twitter"
  },
  "dest": {		//目标索引
    "index": "new_twitter"
  }
}

# 7.x之前的带 type 的写法
将旧索引的 type 下的数据进行迁移
POST _reindex	//固定写法
{
  "source": {	
    "index": "twitter", //老索引
    "type": "twitter",  //老类型
  },
  "dest": {		//目标索引
    "index": "new_twitter"
  }
}

Пример:创建一个新的索引:

PUT /newbank
{
  "mappings": {
    "properties": {
      "account_number": {
        "type": "long"
      },
      "address": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "balance": {
        "type": "long"
      },
      "city": {
        "type": "keyword"
      },
      "email": {
        "type": "keyword"
      },
      "employer": {
        "type": "keyword"
      },
      "firstname": {
        "type": "text"
      },
      "gender": {
        "type": "keyword"
      },
      "lastname": {
        "type": "text"
      },
      "state": {
        "type": "keyword"
      }
    }
  }
}

在这里插入图片描述

数据迁移:

POST _reindex
{
  "source": {
    "index": "bank",
    "type": "account"
  },
  "dest": {
    "index": "newbank"
  }
}

在这里插入图片描述
查看迁移后的数据: Как видите, старые данные можно мигрировать без указания типа.

GET newbank/_search

在这里插入图片描述

Справочная документация-сопоставление

4. Причастие

Одинtokenizer(Токенизатор) получает字符流, который делится на независимыеtokens(леммы, обычно отдельные слова), затем выводtokensпоток.

Например, пробелtokenizerРазделять текст при встрече с пробелами. будет текст "Quick brown fox!"разделить на [Quick,brown,fox!Приходить.

Долженtokenizer(Tokenizer) также отвечает за запись каждогоterm(вход) заказ илиpositionрасположение (дляphraseфразы иword proximityзапрос слова ближайшего соседа) иterm(запись) оригиналword(слово)start(начало) иend(законченныйcharacter offsets(смещение символа) (используется для выделения того, что нужно искать).

ElasticsearchСуществует множество встроенных токенизаторов, которые можно использовать для создания собственных анализаторов.

Протестируйте стандартный токенизатор ES по умолчанию:英文:

POST _analyze
{
  "analyzer": "standard",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

在这里插入图片描述

中文:

POST _analyze
{
  "analyzer": "standard",
  "text": "pafcmall电商项目"
}

在这里插入图片描述

1), установить токенизатор ik

注意: Невозможно установить автоматически с установленным по умолчанию плагином elasticsearch install xxx.zip.

ВходитьGitHub.com/many out/E последний…Найдите соответствующую версию es для установки

1,进入 es 容器内部 plugins 目录

docker exec -it 容器id /bin/bash

wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip

在这里插入图片描述

2. Установкаwget:

yum install wget

在这里插入图片描述

3. Загрузите и подберите версию ESikТокенизатор:

wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip

在这里插入图片描述

4.unzipСкачайте файл и разархивируйте 1), использоватьunzipраспаковыватьelasticsearch-analysis-ik-7.4.2.zipНаходитьunzipКоманда еще не установлена, сначала установите ееunzip

在这里插入图片描述
2), распакуйте файл вpluginsв каталогеikсодержание
在这里插入图片描述
3) Удалить сжатый пакет и датьikДиректория и ее файловая авторизация

rm -rf *.zip
chmod -R 777 ik/

在这里插入图片描述

5. Вы можете подтвердить, установлен ли токенизатор

cd../bin
elasticsearch plugin list:即可列出系统的分词器

1), введите контейнер es в докер

在这里插入图片描述
2), перечислить токенизаторы системы
在这里插入图片描述

6. Перезапустите ES, чтобы токенизатор ik вступил в силу.

docker restart elasticsearch

2), протестировать токенизатор

  • 使用默认分词:
POST _analyze
{
  "analyzer": "standard",
  "text": "pafcmall电商项目"
}

результат:

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l0aY1xXN-1590760088470)(imgs/20-2.png)\]

  • ik智能分词:
POST _analyze
{
  "analyzer": "ik_smart",
  "text": "pafcmall电商项目"
}

результат:

在这里插入图片描述

POST _analyze
{
  "analyzer": "ik_smart",
  "text": "我是中国人"
}

результат:

在这里插入图片描述

  • ik_max_word分词:
POST _analyze
{
  "analyzer": "ik_max_word",
  "text": "我是中国人"
}

результат:

在这里插入图片描述
Видно, что разные токенизаторы имеют очевидные различия в сегментации слов, поэтому при определении индекса в дальнейшем уже нельзя использовать сопоставление по умолчанию, сопоставление нужно создавать вручную, так как токенизатор нужно выбирать.

Справочный документ-анализ

3), пользовательский тезаурус

Сегментация слов по умолчанию в токенизаторе ik не может удовлетворить наши потребности.Для некоторых новых сетевых терминов токенизатор ik не сможет точно идентифицировать сегментацию слов, например:

POST _analyze
{
  "analyzer": "ik_max_word",
  "text": "乔碧萝殿下"
}

После сегментации слова оно отображается следующим образом, вы можете видеть, что токенизатор ik не может распознать, что «Qiao Biluo» — это имя человека:

在这里插入图片描述

Поэтому необходимо настроить тезаурус расширения. Чтобы настроить и расширить тезаурус, вы можете изменить файл конфигурации токенизатора ik, указать удаленный тезаурус и позволить токенизатору ik отправить запрос на удаленное устройство, чтобы получить несколько последних слов, чтобы последние слова использовались в качестве последняя этимология. Существует два способа реализации пользовательского тезауруса:

  1. Внедрите услугу самостоятельно, обработайте запрос токенизатора ik и позвольте токенизатору ik отправить запрос в пользовательский проект.
  2. Создайте сервер nginx, поместите последний тезаурус в nginx, пусть токенизатор ik отправит запрос в nginx, и nginx вернет последний тезаурус в токенизатор ik, чтобы токенизатор ik мог объединить исходный тезаурус и новый словарь.

справка по установке nginx六、附录-安装nginx

Здесь я использую второй способ настройки тезауруса, вам нужно установить nginx перед созданием, пожалуйста, посетитеГлава шестаясвязанный контент. существует/mydata/nginx/html/Создайте новый под путемesкаталог и создать новый тезаурусfenci.txt:

在这里插入图片描述
доступhttp://192.168.56.10/es/fenci.txt, содержимое тезауруса можно запросить:
在这里插入图片描述

Исправлять/usr/share/elasticsearch/plugins/ik/config/серединаIKAnalyzer.cfg.xml

在这里插入图片描述
/usr/share/elasticsearch/plugins/ik/config

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典 -->
        <entry key="ext_dict"></entry>
         <!--用户可以在这里配置自己的扩展停止词字典-->
        <entry key="ext_stopwords"></entry>
        <!--用户可以在这里配置远程扩展字典 -->
        <entry key="remote_ext_dict">http://192.168.56.10/es/fenci.txt</entry>
        <!--用户可以在这里配置远程扩展停止词字典-->
        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

在这里插入图片描述

Примечание: если открытIKAnalyzer.cfg.xmlЕсли он искажен, вы можете сначала выйти из текущего файла и ввести его в командной строке.vi /etc/virc, Затем в файл добавитьset encoding=utf-8, сохранить и выйти, снова открытьIKAnalyzer.cfg.xmlВот и все.

在这里插入图片描述

原来的xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典 -->
        <entry key="ext_dict"></entry>
         <!--用户可以在这里配置自己的扩展停止词字典-->
        <entry key="ext_stopwords"></entry>
        <!--用户可以在这里配置远程扩展字典 -->
        <!-- <entry key="remote_ext_dict">words_location</entry> -->
        <!--用户可以在这里配置远程扩展停止词字典-->
        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

重启 ES:

docker restart elasticsearch 

Снова выполните сегментацию слов в кибане, и вы увидите, что ранее нераспознанное «Qiao Biluo» теперь можно распознать как слово:

在这里插入图片描述

Если у нас появятся новые фразы в будущем, непосредственно в вышеуказанном пользовательском тезаурусеfenci.txtДобавьте его и перезапустите ES.

Так как ES был переустановлен при до этого установленном nginx, необходимо настроить службу автоматического запуска ES:docker update elasticsearch --restart=always

Справочный документ-анализ


5. Elasticsearch-Rest-клиент

Java может манипулировать ES двумя способами: 1) ,9300:TCP(Мы не работаем на 9300, и официальная не рекомендует)

  • spring-data-elasticsearch:transport-api.jar;
    • Версия springboot другая, transport-api.jar другой, и его нельзя адаптировать к версии es
    • Версия 7.x устарела и будет удалена после версии 8.

2),9200:HTTP(Рекомендуемое использование)

  • JestClient: Неофициальное, медленное обновление
  • RestTemplate: для имитации отправки HTTP-запросов многие операции ES нужно инкапсулировать сами по себе, что хлопотно.
  • HttpClient: то же, что и выше I
  • Elasticsearch-Rest-Client: официальный RestClient, который инкапсулирует операции ES, имеет понятный API и прост в запуске.Окончательный выборElasticsearch-Rest-Client(elasticsearch-rest-high-level-client)
    在这里插入图片描述

在这里插入图片描述

1. Интеграция с SpringBoot

1) вpafcmallДобавить новый модуль в проектpafcmall-search, конечно, можно и отдельный проект создать

在这里插入图片描述
Создано с помощью пружинного стартера:
在这里插入图片描述
Добавить кgroupиartifactИнформация:
在这里插入图片描述
Добавить кwebполагаться:
在这里插入图片描述

2), изменитьpomдокумент

Добавьте соответствующий токESверсияrest-high-level-clientЗависимость, я использую7.4.2, так что добавь7.4.2зависимость

<dependency>
	<groupId>org.elasticsearch.client</groupId>
	<artifactId>elasticsearch-rest-high-level-client</artifactId>
	<version>7.4.2</version>
</dependency>

在这里插入图片描述
можно увидеть текущийSpingBoot(2.2.6)Версия, управляемая по умолчаниюESверсия иelasticsearch-rest-high-level-clientВерсии несовместимы:
在这里插入图片描述
нужно изменитьpomфайл, пустьESиelasticsearch-rest-high-level-clientВерсия осталась прежней:

<elasticsearch.version>7.4.2</elasticsearch.version>

在这里插入图片描述

3), добавить класс конфигурации ES

/**
 * @description: Elasticsearch 配置文件
 * <p>
 * SpringBoot 集成 ES 的步骤:
 *  1、导入依赖
 *      https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-getting-started-maven.html
 *  2、编写 ES 配置,给容器中注入一个 RestHighLevelClient,用来操作 9200 端口
 *      https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-getting-started-initialization.html
 *  3、参照官方API
 */
@Configuration
public class PafcmallElasticsearchConfig {

    @Bean
    public RestHighLevelClient esRestHighLevelClient() {
        RestHighLevelClient client = new RestHighLevelClient(
                // 这里可以配置多个 es服务,我当前服务不是集群,所以目前只配置一个
                RestClient.builder(
                        new HttpHost("192.168.50.10", 9200, "http")));

        return client;
    }
}

在这里插入图片描述
修改启动类:

@EnableDiscoveryClient // 开启服务注册与发现
// 这里需要排除一下数据库的依赖,因为引入了pafcmall-common依赖,其中包含了mybatis-plus的配置,目前我们的服务还没有依赖数据源,所以需要排除
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class PafcmallSearchApplication {

    public static void main(String[] args) {
        SpringApplication.run(PafcmallSearchApplication.class, args);
    }

}

Исправлятьapplication.propertiesдокумент:

# nacos配置中心地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# 配置应用名
spring.application.name=pafcmall-search

Используйте тестовый класс для проверки:

@SpringBootTest
class PafcmallSearchApplicationTests {
    @Autowired
    private RestHighLevelClient client;
	
    @Test
    void contextLoads() {
        System.out.println(client);
    }
}

在这里插入图片描述
Для получения дополнительной информации об интеграции см.java-rest-high-getting-started-mavenиjava-rest-high-getting-started-initialization

2. Конфигурация

1),настроитьсуществуетPafcmallElasticsearchConfigДобавьте следующую конфигурацию в класс конфигурации:

    public static final RequestOptions COMMON_OPTIONS;
    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
		// 这里先注释掉,目前没有用到,后边用到了再解释
//        builder.addHeader("Authorization", "Bearer " + TOKEN);
//        builder.setHttpAsyncResponseConsumerFactory(
//                new HttpAsyncResponseConsumerFactory
//                        .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
        COMMON_OPTIONS = builder.build();
    }

2),контрольная работасуществуетPafcmallSearchApplicationTestsДобавьте следующий код в тестовый класс:

    /**
     * 测试存储数据到es
     * 更新也是可以的
     */
    @Test
    void indexData() throws IOException {
        // 准备数据
        IndexRequest indexRequest = new IndexRequest("users");//索引名
        indexRequest.id("1");//数据id

        // 第一种方式
//        indexRequest.source("userName", "zhangsan", "age", 18, "gender", "男");

        // 第二种方式(推荐使用)
        User user = new User();
        user.setUserName("zhangsan");
        user.setAge(18);
        user.setGender("男");

        String jsonString = JSON.toJSONString(user);
        indexRequest.source(jsonString,XContentType.JSON); //要保存的内容

        // 执行操作
        IndexResponse index = client.index(indexRequest, PafcmallElasticsearchConfig.COMMON_OPTIONS);

        // 提取有用的数据相应
        System.out.println(index);
    }

    @Data
    class User{
        private String userName;
        private Integer age;
        private String gender;
    }

Выполнив тест, вы увидите, что индекс был успешно создан:

在这里插入图片描述
Запрос в кибане:
在这里插入图片描述

Для получения дополнительной информации о конфигурации см.java-rest-high-getting-started-request-optionsиjava-rest-low-usage-request-options

3. Используйте

В предыдущем разделе реализовано создание индекса, в этом разделе попробуем функцию извлечения данных. реализовать в коде搜索address中包含mill的所有人的年龄分布以及平均薪资Эта функциональность в кибане использует следующий оператор DSL:

GET /bank/_search
{
  "query": { //查询
    "match": {
      "address": "mill"
    }
  },
  "aggs": { //聚合
    "ageAgg": { //年龄分布
      "terms": {
        "field": "age",
        "size": 10 //只取10中聚合的结果
      }
    },
    "balanceAvg":{//平均薪资
      "avg": {
        "field": "balance"
      }
    }
  }
}

Результат показан ниже:

在这里插入图片描述

Как это реализовать в интегрированной среде SpringBoot? Давайте используем код для реализации вышеуказанных функций.

1), тестовый классPafcmallSearchApplicationTests.javaдобавить метод тестированияsearchData():

/**
 * 检索数据
 *
 * @throws IOException
 */
@Test
void searchData() throws IOException {
    // 1、创建检索请求
    SearchRequest searchRequest = new SearchRequest();
    // 指定索引
    searchRequest.indices("bank");
    // 指定DSL,检索条件
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    // 1.1)、构造检索条件
    //        sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
    //        sourceBuilder.from(0);
    //        sourceBuilder.size(5);
    //        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

    searchSourceBuilder.query(QueryBuilders.matchQuery("address","mill"));

    // 聚合数据
    // 1.2)、根据年龄分布聚合
    TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
    searchSourceBuilder.aggregation(ageAgg);

    // 1.3)、计算平薪资
    AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
    searchSourceBuilder.aggregation(balanceAvg);

    System.out.println("检索条件:"+searchSourceBuilder.toString());
    searchRequest.source(searchSourceBuilder);

    // 2、执行检索
    SearchResponse searchResponse = client.search(searchRequest, PafcmallElasticsearchConfig.COMMON_OPTIONS);

    // 3、分析结果 searchResponse
    System.out.println(searchResponse.toString());

    //3.1)、获取所有查到的数据
    SearchHits hits = searchResponse.getHits(); // 获取到最外围的 hits
    SearchHit[] searchHits = hits.getHits(); // 内围的 hits 数组
    for (SearchHit hit : searchHits) {
        /**
             * "_index":"bank",
             *        "_type":"account",
             *        "_id":"970",
             *        "_score":5.4032025,
             *        "_source":{
             */
        //            hit.getIndex();hit.getType()''
        String str = hit.getSourceAsString();
        Account account = JSON.parseObject(str, Account.class);

        System.out.println(account.toString());

    }
    //3.1)、获取这次检索到的分析数据
    Aggregations aggregations = searchResponse.getAggregations();
    // 可以遍历获取聚合数据
    //        for (Aggregation aggregation : aggregations.asList()) {
    //            System.out.println("当前聚合:"+aggregation.getName());
    //            aggregation.getXxx
    //        }
    // 也可使使用下面的方式
    Terms ageAgg1 = aggregations.get("ageAgg");
    for (Terms.Bucket bucket : ageAgg1.getBuckets()) {
        String keyAsString = bucket.getKeyAsString();
        System.out.println("年龄:"+keyAsString+" ==> 有 "+bucket.getDocCount()+" 个");
    }

    Avg balanceAvg1 = aggregations.get("balanceAvg");
    System.out.println("平均薪资:"+balanceAvg);
}

2), добавьте тестовый класс, который собирает результаты:

/**
 * 测试用账号类
 */
@ToString
@Data
static class Account {
	private int account_number;
	private int balance;
	private String firstname;
	private String lastname;
	private int age;
	private String gender;
	private String address;
	private String employer;
	private String email;
	private String city;
	private String state;
}

3), выполните тестовый метод, результаты следующие:

在这里插入图片描述

在这里插入图片描述
Вы можете видеть, что естьboostПараметры, это автоматически добавляется системой для нас, что было недоступно, когда мы использовали язык DSL для извлечения данных в кибане раньше. тогда этоboostчто это? Ссылаться наофициальная документация, можно сделать вывод.
在这里插入图片描述

在这里插入图片描述

Глядя на результаты запроса, вы можете использовать инструмент json для форматирования, и вы можете увидеть, что есть 4 возвращаемых данных, которые соответствуют условиям, которые соответствуют тем, которые были найдены в kibana ранее:

在这里插入图片描述

Выше приведено полное содержание интеграции SpringBoot с ES.Для более продвинутого использования вы можете обратиться к официальной документации ES, чтобы попробовать.

Для получения дополнительной информации о поиске см.java-rest-high-search

Справочная документация-java-остальное

Суммировать

Конечно, ES широко используется в реальном производстве:

такие как использованиеELKкомпоненты используются для日志的收集или выполнить全文的检索:

在这里插入图片描述

или использовать收集异常信息, сделать визуальный интерфейс для анализа и т.д.:

在这里插入图片描述
Больше сценариев приложений необходимо сочетать с реальным производством, и нам также нужно попробовать и изучить их самостоятельно.


6. Приложение — Установка nginx

1. Переустановите ЕС

Перед установкой nginx нужно переустановить ES, так как максимальный параметр памяти установленного ранее ES 128M, при использовании будут разные проблемы, а сейчас изменено на 512M, самый быстрый способ удалить исходный контейнер, а потом перезапустить Создать. Так не потеряются ли данные предыдущего ES? Ответ - нет. Поскольку я сопоставил каталог файлов при установке ES ранее, все файлы данных хранятся на виртуальной машине, а не в контейнере докеров.

docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2

# docker run --name elasticsearch 创建一个es容器并起一个名字;
# -p 9200:9200 将linux的9200端口映射到docker容器的9200端口,用来给es发送http请求
# -p 9300:9300 9300是es在分布式集群状态下节点之间的通信端口  \ 换行符
# -e 指定一个参数,当前es以单节点模式运行
# *注意,ES_JAVA_OPTS非常重要,指定开发时es运行时的最小和最大内存占用为64M和128M,否则就会占用全部可用内存
# -v 挂载命令,将虚拟机中的路径和docker中的路径进行关联
# -d 后台启动服务

在这里插入图片描述

2. Установите Nginx

  • существует/mydataСоздайте новый в каталогеnginxкаталог, в конце концовnginxДанные для установки размещены здесь:

    在这里插入图片描述

  • Просто запустите случайный экземпляр nginx, чтобы скопировать конфигурацию:

docker run -p 80:80 --name nginx -d nginx:1.10 #如果当前本地docker镜像中没有nginx,那么它会自动下载并创建一个并服务

在这里插入图片描述

  • Скопируйте файл конфигурации из контейнера в текущий каталог:
docker container cp nginx:/etc/nginx .

别忘了后面的点

在这里插入图片描述

  • Завершить исходный контейнер:docker stop nginx

  • Выполните команду, чтобы удалить исходный контейнер:docker rm $Containerld

    在这里插入图片描述

  • Измените имя файла:mv nginx confпереместить эту конфу в/mydata/nginxВниз

    在这里插入图片描述

  • Создайте новый nginx и выполните следующую команду

docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.10

在这里插入图片描述

  • доступhttp://192.168.56.10/, вы можете видеть, что сервер nginx был успешно установлен
    在这里插入图片描述

Поскольку текущий nginx не указывает страницу по умолчанию, она будет отображаться при посещении403ошибка, это нормально Если вы хотите установить страницу доступа по умолчанию, вы можете/mydata/nginx/htmlСоздайте новый в каталогеindex.htmlфайл с прикрепленным кодом:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h1>PafcMall</h1>
	</body>
</html>

在这里插入图片描述

вернутьсяhttp://192.168.56.10/:

在这里插入图片描述


Дополнение - Vagrant создает виртуальную машину - изменяет сетевые настройки Linux и включает доступ к паролю root

1. Изменить сетевые настройки Linux

1、进入网卡设置目录下

cd sysconfig/network-scripts/

在这里插入图片描述

2、查看当系统前网卡信息

ip addr

在这里插入图片描述

3、修改网卡地址,添加网关和 DNS 服务

vi ifcfg-eth1

在这里插入图片描述

NM_CONTROLLED=yes
BOOTPROTO=none
ONBOOT=yes
IPADDR=192.168.56.10
NETMASK=255.255.255.0
GATEWAY=192.168.56.1
DNS1=114.114.114.114
DNS2=8.8.8.8
DEVICE=eth1
PEERDNS=no

在这里插入图片描述

service network restart

在这里插入图片描述

4、配置新的 yum 源,提升软件安装下载速度

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
yum makecache #使新的yum源生效

在这里插入图片描述

2. Включите доступ с паролем root

1、修改 sshd_config 文件

vi /etc/ssh/sshd_config  # Vagrant ssh进去系统之后,修改sshd_config文件

在这里插入图片描述

PasswordAuthentication yes/no # 修改 no 为 yes

在这里插入图片描述

2、重启服务

service sshd restart

在这里插入图片描述


Ссылаться на:

Elasticsearch Reference

elastic

Руководство по началу работы с полнотекстовой поисковой системой Elasticsearch