@[toc]
Введение
Полнотекстовый поиск является наиболее распространенным требованием, и 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: просмотреть все узлы
- GET /_cat/health: просмотреть состояние работоспособности es
- GET /_cat/master: просмотреть главный узел
- GET /_cat/indices: просмотреть все индексы; эквивалентно MySQL
show databases
;
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 помог нам сгенерировать идентификатор:
Итак, вопрос в том, в чем разница между методами 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
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, и выдается оценка корреляции.
4), match_phrase [фразовое соответствие]
Получить значение для сопоставления как целое слово (без сегментации слов)
Например: узнать, что адрес содержитmill road
Все записи и дать оценку релевантности
GET /bank/_search
{
"query": {
"match_phrase": {
"address": "mill road"
}
}
}
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"]
}
}
}
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 Таким образом, баллы за все документы будут возвращены. |
Давайте посмотрим в следующем разделеfilter
Фильтрация результатов.
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
}
}
}
}
}
}
8), срок
То же, что матч. Соответствует значению атрибута.全文检索字段用 match,其他非 text 字段匹配用 term
.
Avoid using the
term
query fortext
fields.By default, Elasticsearch changes the values of
text
fields as part of analysis. This can make finding exact matches fortext
field values difficult.To search
text
field values, use thematch
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:Справочная документация-поиск-агрегации
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
) запрос
- Тип IP (IP)
Дополнительные типы полей см. в официальной документации 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
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电商项目"
}
результат:
-
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 отправить запрос на удаленное устройство, чтобы получить несколько последних слов, чтобы последние слова использовались в качестве последняя этимология. Существует два способа реализации пользовательского тезауруса:
- Внедрите услугу самостоятельно, обработайте запрос токенизатора ik и позвольте токенизатору ik отправить запрос в пользовательский проект.
- Создайте сервер nginx, поместите последний тезаурус в nginx, пусть токенизатор ik отправит запрос в nginx, и nginx вернет последний тезаурус в токенизатор ik, чтобы токенизатор ik мог объединить исходный тезаурус и новый словарь.
справка по установке nginx
六、附录-安装nginx
Здесь я использую второй способ настройки тезауруса, вам нужно установить nginx перед созданием, пожалуйста, посетитеГлава шестаясвязанный контент.
существует/mydata/nginx/html/
Создайте новый под путем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