Учебный документ по ElasticSearch

Elasticsearch

Глава 1. Начало работы с ElasticSearch

Раздел 1. Обзор ElasticSearch

1.1 ElasticSearch — это поисковый сервер на базе Lucene.

Он предоставляет распределенную многопользовательскую полнотекстовую поисковую систему на основе веб-интерфейса RESTful. ElasticSearch разработан на Java, Выпущенный с открытым исходным кодом в соответствии с условиями лицензии Apache, это популярная в настоящее время корпоративная поисковая система. Разработанный для использования в облачных вычислениях, он обеспечивает поиск в реальном времени, стабильный, надежный, быстрый и простой в установке и использовании. построен полностью Elasticsearch, основанный на программном обеспечении с открытым исходным кодом Lucene, может не только выполнять распределенное индексирование и поиск массивных данных, но и обеспечивать анализ агрегации данных. Согласно статистике DB-Engines, международного авторитетного агентства по оценке продуктов баз данных, в январе 2016 года Elasticsearch превзошел Solr и другие и стал приложением для поисковых систем номер один. Резюме: инструмент полнотекстового поиска для высокомасштабируемого и высокодоступного анализа данных в реальном времени на основе стандартов Restful.

1.2 Основные понятия ElasticSearch

Index

Аналогично базе данных в базе данных mysql

Type

Подобно таблице table в базе данных mysql, в es тип (таблица) может быть установлен в индексе и отображен путем сопоставления.

Document

Поскольку данные, хранящиеся в es, относятся к типу документа, часть данных, соответствующая документу, эквивалентна строке строки данных в базе данных mysql. Документ может иметь несколько полей, то есть база данных mysql может иметь несколько столбцов подряд.

Field

Несколько столбцов, соответствующих документу в es, соответствуют каждому столбцу в базе данных mysql.

Mapping

Это можно понимать как соответствующую схему в mysql или solr, но иногда сопоставление в es добавляет функцию динамического распознавания, которая кажется очень мощной. На самом деле не рекомендуется использовать его в реальной производственной среде, лучше всего начать с формулирования соответствующей схемы.

indexed

Это номинальная индексация. В mysql соответствующие индексы обычно добавляются к часто используемым столбцам для повышения скорости запросов, а в es они добавляются по умолчанию. В индексе, если вы не сделаете специальную формулу, он не будет индексироваться, а будет храниться только для отображения.Это необходимо установить в соответствии с вашими конкретными потребностями и бизнесом.

Query DSL

Подобно оператору sql mysql, но в es это оператор запроса в формате json, профессиональный термин называется: QueryDSL

GET/PUT/POST/DELETE

Аналогично выбору/обновлению/удалению в mysql соответственно...

1.3 Архитектура Elasticsearch

image

Уровень шлюза

es — это файловая система, используемая для хранения индексных файлов, и она поддерживает множество типов, таких как: локальный диск, общее хранилище (необходимо для моментального снимка), hadoop Распределенное хранилище HDFS, Amazon S3. Его основная обязанность — сохранять данные в течение длительного времени и восстанавливать данные через шлюз после перезапуска всего кластера.

Distributed Lucene Directory

Верхний уровень Gateway представляет собой распределенную структуру lucene, lucene предназначена для поиска, но это автономная поисковая система, такая как эта система распределенной поисковой системы. Система, хотя нижний уровень использует lucene, ему необходимо запускать lucene на каждом узле для соответствующей индексации, запросов и обновлений, поэтому это должна быть распределенная операция. линейная структура для удовлетворения потребностей бизнеса.

Четыре модульных компонента

Над районным каталогом lucene находятся несколько модулей es.

1.Index ModuleЭто индексный модуль, который предназначен для построения индекса по данным, что обычно называется созданием каких-то инвертированных индексов и т. д.;

2.Search ModuleЭто модуль поиска, предназначенный для запроса и поиска данных;

3.MappingМодуль представляет собой модуль сопоставления и синтаксического анализа данных, то есть каждое поле ваших данных может быть сопоставлено и проанализировано посредством сопоставления в соответствии с установленной вами структурой таблицы.Если у вас нет структуры таблицы, es сделает вывод о вас на основе вашей тип данных. После структуры данных создайте сопоставление самостоятельно, а затем проанализируйте свои данные в соответствии с этим сопоставлением;

4.RiverМодуль надо отменять после es2.0, значит это сторонний плагин, например через прошивку Некоторые пользовательские сценарии напрямую синхронизируют источники данных, такие как традиционные базы данных (mysql), с кластером es после форматирования и преобразования. Большая часть этой реки написана сама по себе, и качество написанного неравномерно.Интеграция этих вещей в эс вызовет Многие внутренние ошибки серьезно повлияли на нормальное применение es, поэтому рассмотрите возможность их удаления после es2.0.

Открытие, Сценарий

Существует модуль обнаружения поверх компонентов модуля es4: es — это кластер, содержащий множество узлов, многим узлам необходимо обнаружить друг друга, а затем сформировать кластер, включая выбор В основном это все используемые модули обнаружения, по умолчанию используется Zen или может использоваться EC2; запросы es также могут поддерживать различные сценарии, то есть языки сценариев, в том числе mvel, js, python и т. д.

Уровень транспортного протокола

Следующий уровень — это коммуникационный интерфейс es Transport, который поддерживает больше: Thrift, Memcached и Http, по умолчанию — http, JMX — один из java. Фреймворк удаленного мониторинга и управления, поскольку es реализуется через java.

Уровень интерфейса RESTful

Верхний уровень — это интерфейс доступа, предоставляемый нам es.Официально рекомендуемым решением является этот интерфейс Restful, который напрямую отправляет http-запросы для облегчения последующего использования nginx в качестве прокси, Распространение включает в себя управление разрешениями, которое можно будет сделать позже, и это управление легко сделать через http. Если используется Java-клиент, он напрямую вызывает API и выполняет балансировку нагрузки для И управление разрешениями все еще не очень хорошо.

1.4 RESTful API

Архитектурный стиль программного обеспечения, стиль проектирования, а не стандарт, просто обеспечивает набор принципов и ограничений проектирования. Он в основном используется для программного обеспечения взаимодействия клиент-сервер. Программное обеспечение, разработанное на основе этого стиля, может быть более кратким, более иерархичным и простым в реализации таких механизмов, как кэширование. Среди трех основных современных схем взаимодействия веб-сервисов REST сравнивается с S OAP (Simple Object Access Protocol, простой протокол доступа к объектам) и XML-RPC более просты и понятны.

(Representational State Transfer 意思是:表述性状态传递)

它使用典型的HTTP方法,诸如GET,POST.DELETE,PUT来实现资源的获取,添加,修改,删除等操作。即通过HTTP动词来实现资源的状态扭转


GET 用来获取资源

POST 用来新建资源(也可以用于更新资源)

PUT 用来更新资源

DELETE 用来删除资源

1.5 Команда CRUL

以命令的方式执行HTTP协议的请求
GET/POST/PUT/DELETE

示例:
访问一个网页

curl www.baidu.com

curl -o tt.html www.baidu.com

显示响应的头信息

curl -i www.baidu.com

显示一次HTTP请求的通信过程

curl -v www.baidu.com

执行GET/POST/PUT/DELETE操作

curl -X GET/POST/PUT/DELETE url

1.6 Установите ElasticSearch6.2.4 под CentOS7

Настройте среду JDK

配置环境变量
export JAVA_HOME="/opt/jdk1.8.0_144"

export PATH="$JAVA_HOME/bin:$PATH"

export CLASSPATH=".:$JAVA_HOME/lib"

Установите ElasticSearch6.2.4

ссылка для скачивания:woohoo.elastic.co/capable/download…

Ошибка запуска:

image

Решение: bin/elasticsearch -Des.insecure.allow.root=true

Или измените bin/elasticsearch и добавьте свойство ES_JAVA_OPTS: ES_JAVA_OPTS="-Des.insecure.allow.root=true"

Начать заново:

image

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

Создайте группы пользователей и пользователей:

groupadd esgroup

useradd esuser -g esgroup -p espassword

Измените пользователя и группу папки elasticsearch и внутренних файлов:

cd /opt

chown -R esuser:esgroup elasticsearch-6.2.4

Смените пользователя и запустите:

su esuser

./bin/elasticsearch

Повторный запуск показывает, что убито:

image

Необходимо настроить размер памяти JVM:

vi bin/elasticsearch

ES_JAVA_OPTS="-Xms512m -Xmx512m"

Начать снова: начать успешно

Если отображается сообщение, похожее на следующее:

[INFO ][o.e.c.r.a.DiskThresholdMonitor] [ZAds5FP] low disk watermark [85%] exceeded on     [ZAds5FPeTY-ZUKjXd7HJKA][ZAds5FP][/opt/elasticsearch-6.2.4/data/nodes/0] free: 1.2gb[14.2%],     replicas will not be assigned to this node

Необходимо очистить место на диске.

Запуск в фоновом режиме: ./bin/elasticsearch -d

Тестовое соединение: curl 127.0.0.1:9200

Вы увидите данные JSON:

[root@localhost ~]# curl 127.0.0.1:9200
  {
  "name" : "rBrMTNx",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "-noR5DxFRsyvAFvAzxl07g",
  "version" : {
    "number" : "5.1.1",
    "build_hash" : "5395e21",
    "build_date" : "2016-12-06T12:36:15.409Z",
    "build_snapshot" : false,
    "lucene_version" : "6.3.0"
  },
  "tagline" : "You Know, for Search"
 }

Реализовать удаленный доступ: Config/elasticsearch.yml необходимо настроить: сеть.хост: 192.168.25.131

Запустите снова и сообщите об ошибке:

image

Обработайте первую ошибку:

vim /etc/security/limits.conf //Файл добавляется в конец

esuser soft nofile 65536

esuser hard nofile 65536

esuser soft nproc 4096

esuser hard nproc 4096

Обработайте вторую ошибку:

Войдите в каталог limit.d, чтобы изменить файл конфигурации.

vim /etc/security/limits.d/20-nproc.conf. Модифицировано для Esuser Soft NProc 4096

Обработайте третью ошибку:

vim /etc/sysctl.conf

vm.max_map_count=655360

Выполните следующую команду, чтобы она вступила в силу: sysctl -p

Отключите брандмауэр: systemctl stop firewalld.service

Запустил снова успешно!

1.7 Установите плагин Head

Head — это инструмент управления кластером для elasticsearch, который можно использовать для просмотра данных и запросов.

(1) elasticsearch-head — это программное обеспечение с открытым исходным кодом, размещенное на github, поэтому, если мы хотим его использовать, мы должны сначала установить git и получить elasticsearch-head через git

(2) Run Elasticsearch-Guade будет использовать Grunt, и Grunt Trans Trans Trans Trans Trans Trans Trans NPM, поэтому Nodejs необходимо для установки.

(3) Начиная с elasticsearch 5.0, elasticsearch-head не размещается в качестве плагина в своем каталоге плагинов. Используйте git для копирования elasticsearch-head на локальный

cd /usr/local/

git clone git://github.com/mobz/elasticsearch-head.git

(4) Установите пакет зависимостей elasticsearch-head

[root@localhost local]# npm install -g grunt-cli

[root@localhost _site]# cd /usr/local/elasticsearch-head/

[root@localhost elasticsearch-head]# cnpm install

(5) Изменить Gruntfile.js

[root@localhost _site]# cd /usr/local/elasticsearch-head/

[root@localhost elasticsearch-head]# vi Gruntfile.js

Добавьте в connect-->server-->options: имя хоста: '*', чтобы разрешить доступ всем IP-адресам

(6) Изменить адрес подключения по умолчанию для elasticsearch-head. [root@localhost elasticsearch-head]# cd /usr/local/elasticsearch-head/_site/

[root@localhost _site]# vi app.js

Поместите this.base_uri = this.config.base_uri || this.prefs.get("app-base_uri") || "http://localhost:9200"; localhost изменен на адрес вашего сервера es

(7) Настройте elasticsearch, чтобы разрешить междоменный доступ

Откройте файл конфигурации elasticsearch elasticsearch.yml и добавьте следующие две строки кода в конец файла:

http.cors.enabled: true

http.cors.allow-origin: "*"

(8) Открытый порт 9100

[root@localhost elasticsearch-head]# firewall-cmd --zone=public --add-port=9100/tcp --permanent

перезапустить брандмауэр

[root@localhost elasticsearch-head]# firewall-cmd --reload

(9) Начать эластичный поиск

(10) Запускаем elasticsearch-head

[root@localhost _site]# cd /usr/local/elasticsearch-head/

[root@localhost elasticsearch-head]# node_modules/grunt/bin/grunt server

(11) Посетите elasticsearch-head

Отключите брандмауэр: systemctl stop firewalld.service

Входной URL-адрес браузера:http://192.168.25.131:9100/

1.8 Установите Кибану

Kibana — это платформа анализа и визуализации с открытым исходным кодом для Elasticsearch. С помощью Kibana вы можете запрашивать, просматривать и взаимодействовать с данными, хранящимися в индексах ES. Используя Kibana, вы можете выполнять расширенный анализ данных и просматривать их в виде диаграмм, таблиц, и карты.данные

(1) Скачать Кибануwoohoo.elastic.co/downloads/…

(2) Скопируйте загруженный сжатый пакет в каталог /soft.

(3) Разархивируйте и переместите разархивированный каталог в /user/local/kibana.

(4) Отредактируйте файл конфигурации kibana

[root@localhost /]# vi /usr/local/kibana/config/kibana.yml

image

Измените server.host, elasticsearch.url на IP-адрес сервера, на котором он расположен.

(5) Откройте порт 5601

Порт по умолчанию для Kibana — 5601.

Включите брандмауэр: systemctl запустите firewalld.service

Откройте порт 5601: firewall-cmd --permanent --zone=public --add-port=5601/tcp

Перезапустите брандмауэр: firewall-cmd –reload

(6) Запустить Кибану

[root@localhost /]# /usr/local/kibana/bin/kibana

Доступ через браузер:http://192.168.25.131:5601

1.9 Установить китайский токенизатор

(1) Скачать китайский токенизаторGitHub.com/many out/E последний…

下载elasticsearch-analysis-ik-master.zip

(2) Разархивируйте elasticsearch-analysis-ik-master.zip

unzip elasticsearch-analysis-ik-master.zip

(3) Введите elasticsearch-analysis-ik-master и скомпилируйте исходный код.

mvn clean install -Dmaven.test.skip=true

(4) Создайте каталог ik в папке плагинов es

(5) Переместите сгенерированный после компиляции файл elasticsearch-analysis-ik-version.zip в ik и распакуйте его.

(6) Переместите распакованный контент в каталог ik

Раздел 2 Основные операции ElasticSearch

2.1 Перевернутый индекс

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

Пример:

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

(2): В разных языках, таких как китайский и английский, между словами нет четких разделительных символов, поэтому, прежде всего, используется система сегментации слов для автоматического разделения документа на последовательности слов. Таким образом, каждый документ преобразуется в поток данных, составленный из последовательностей слов.Для удобства последующей обработки системой необходимо присвоить каждому отдельному слову уникальный номер слова, и при этом зафиксировать, какие документы содержат это слово После такой обработки можно получить простейший инвертированный индекс

В столбце «Идентификатор слова» записывается номер слова каждого слова, во втором столбце — соответствующее слово, а в третьем столбце — инвертированный список, соответствующий каждому слову.

(3): В дополнение к этому система индексирования также может записывать дополнительную информацию. На следующем рисунке также записывается информация о частоте слов (TF), то есть количество вхождений этого слова в определенный документ. Причина записи этого Информация заключается в том, что информация о частоте слов является важным расчетным фактором при расчете сходства между запросом и документом при сортировке результатов поиска, поэтому она записывается в инвертированный список для облегчения расчета балла при последующей сортировке.

(4): Информация о положении слова в документе также может быть записана в инвертированном списке.

(1,<11>,1),(2,<7>,1),(3,<3,9>,2)

С помощью этой системы индексации поисковая система может легко ответить на запрос пользователя.Например, пользователь вводит слово запроса «facebook», поисковая система находит индекс обратной строки, может прочитать документ, содержащий это слово, который предоставляется для В результатах поиска информация о частоте слов, информация о частоте документов может быть отсортирована, сходство этих результатов поиска кандидатов, вычисление документа и запроса, в соответствии с оценкой сходства, вывод от высокого к низкому, так что какой-то внутренний поток поисковой системы.

2.1.2 Принцип перевернутого индекса

1.The quick brown fox jumped over the lazy dog

2.Quick brown foxes leap over lazy dogs in summer

Перевернутый индекс:

Term Doc_1 Doc_2
Quick X
The X
brown X X
dog X
dogs X
fox X
foxes X
in X
jumped X
lazy X X
leap X
over X X
quick X
summer X
the X

Поиск быстрого коричневого:

Term Doc_1 Doc_2
brown X X
quick X
Total 2 1

При расчете оценки релевантности степень соответствия документа 1 высока, и оценка будет выше, чем у документа 2.

проблема:

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

fox и fox очень похожи, как собака и собаки, у них один и тот же корень.

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

Поиск документов, содержащих Quick fox, недоступен для поиска

Используйте правила нормализации: Когда установлен инвертированный индекс, каждое разделенное слово будет обрабатываться соответствующим образом, чтобы повысить вероятность того, что связанные документы могут быть найдены при последующем поиске.

Term Doc_1 Doc_2
brown X X
dog X X
fox X X
in X
jump X X
lazy X X
over X X
quick X X
summer X
the X X

2.1.3 Знакомство с токенизатором и встроенным токенизатором

Токенизатор: вырезайте термины один за другим из строки текста и нормализуйте каждый термин.

Включает в себя три части:

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

токенизатор: сегментация слов

фильтр токенов: нормализация

Встроенный токенизатор:

стандартный токенизатор: (по умолчанию) он преобразует лексические единицы в нижний регистр, удаляет стоп-слова и знаки препинания и поддерживает метод, используемый в китайском языке для сегментации слов.

простой токенизатор: сначала разбивает текстовую информацию по неалфавитным символам, а затем объединяет лексические единицы в нижний регистр. Анализатор удаляет символы числового типа.

Токенизатор пробелов: он удаляет только пробелы, не переводит символы в нижний регистр и не поддерживает китайский язык; И никакая другая обработка нормализации не выполняется для сгенерированных лексических единиц.

языковой токенизатор: токенизатор для определенного языка, китайский не поддерживается

2.2 Внедрение CRUD с помощью ElasticSearch API

Добавить индекс:

PUT /lib/

{

  "settings":{
  
      "index":{
      
        "number_of_shards": 5,
        
        "number_of_replicas": 1
        
        }
        
      }
}

PUT  lib

Просмотр информации об индексе:

GET /lib/_settings

GET _all/_settings

Добавьте документацию:

PUT /lib/user/1

{
    "first_name" :  "Jane",
    
    "last_name" :   "Smith",
    
    "age" :         32,
    
    "about" :       "I like to collect rock albums",
    
    "interests":  [ "music" ]
}

POST /lib/user/

{
    "first_name" :  "Douglas",
    
    "last_name" :   "Fir",
    
    "age" :         23,
    
    "about":        "I like to build cabinets",
    
    "interests":  [ "forestry" ]
    
}

Посмотреть документацию:

GET /lib/user/1

GET /lib/user/

GET /lib/user/1?_source=age,interests

Обновить документацию:

PUT /lib/user/1

{
    "first_name" :  "Jane",
    
    "last_name" :   "Smith",
    
    "age" :         36,
    
    "about" :       "I like to collect rock albums",
    
    "interests":  [ "music" ]
}

POST /lib/user/1/_update

{

  "doc":{
  
      "age":33
      
      }
}

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

DELETE /lib/user/1

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

DELETE /lib

2.3 Получение документов пакетами

Используйте Multi Get API, предоставленный es:

Используя Multi Get API, вы можете получить набор документов за один раз по имени индекса, имени типа и идентификатору документа.Документы могут поступать из одной библиотеки индексов или из разных библиотек индексов.

Используйте команду curl:

curl 'http://192.168.25.131:9200/_mget' -d '{

"docs":[

   {
   
    "_index": "lib",
    
    "_type": "user",
    
    "_id": 1
    
   },
   
   {
   
     "_index": "lib",
     
     "_type": "user",
     
     "_id": 2
     
   }

  ]
}'

В клиентских инструментах:

GET /_mget

{
   
    "docs":[
       
       {
           "_index": "lib",
           "_type": "user",
           "_id": 1
       },
       {
           "_index": "lib",
           "_type": "user",
           "_id": 2
       },
       {
           "_index": "lib",
           "_type": "user",
           "_id": 3
       }
       
     ]
}

Можно указать конкретные поля:

GET /_mget

{
   
    "docs":[
       
       {
           "_index": "lib",
           "_type": "user",
           "_id": 1,
           "_source": "interests"
       },
       {
           "_index": "lib",
           "_type": "user",
           "_id": 2,
           "_source": ["age","interests"]
       }
       
     ]
}

Получить разные документы одного типа с одним и тем же индексом:

GET /lib/user/_mget

{
   
    "docs":[
       
       {
           "_id": 1
       },
       {
           "_type": "user",
           "_id": 2,
       }
       
     ]
}

GET /lib/user/_mget

{
   
   "ids": ["1","2"]
   
}

2.4 Используйте Bulk API для реализации массовых операций

массовый формат:

{action:{metadata}}\n

{requstbody}\n

action:(行为)

  create:文档不存在时创建
  
  update:更新文档
  
  index:创建新文档或替换已有文档
  
  delete:删除一个文档
  
metadata:_index,_type,_id

Разница между созданием и индексированием

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

Пример:

{"delete":{"_index":"lib","_type":"user","_id":"1"}}

Массовое добавление:

POST /lib2/books/_bulk

{"index":{"_id":1}}

{"title":"Java","price":55}

{"index":{"_id":2}}

{"title":"Html5","price":45}

{"index":{"_id":3}}

{"title":"Php","price":35}

{"index":{"_id":4}}

{"title":"Python","price":50}

Массовое приобретение:

GET /lib2/books/_mget
{

"ids": ["1","2","3","4"]
}

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

POST /lib2/books/_bulk

{"delete":{"_index":"lib2","_type":"books","_id":4}}

{"create":{"_index":"tt","_type":"ttt","_id":"100"}}

{"name":"lisi"}

{"index":{"_index":"tt","_type":"ttt"}}

{"name":"zhaosi"}

{"update":{"_index":"lib2","_type":"books","_id":"4"}}

{"doc":{"price":58}}

Максимальный объем данных, которые может обрабатывать массив за один раз:

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

   Общая рекомендация: 1000–5000 документов, рекомендуемый размер – 5–15 МБ. По умолчанию не может превышать 100 МБ. Он может быть указан в файле конфигурации es (например, elasticsearch.yml в разделе config в разделе $ES_HOME).   

2.5 Контроль версий

ElasticSearch использует оптимистическую блокировку для обеспечения согласованности данных, то есть, когда пользователь работает с документом, ему не нужно блокировать и разблокировать документ, а нужно только указать версию для работы. Если номера версий совпадают, ElasticSearch позволит выполнить операцию гладко, а при наличии конфликта в номерах версий ElasticSearch уведомит о конфликте и создаст исключение (VersionConflictEngineException).

Значение номера версии ElasticSearch находится в диапазоне от 1 до 2^63-1.

Внутренний контроль версий: используется _version

Внешнее управление версиями: elasticsearch обрабатывает внешние номера версий немного иначе, чем внутренние номера версий. Вместо того, чтобы проверять, совпадает ли _version со значением, указанным в запросе, он проверяет, меньше ли текущее _version указанного значения. Если запрос выполнен успешно, номер внешней версии будет сохранен в _version в документе.

Чтобы _version соответствовал внешним версиям данных использовать version_type = внешний

2.6 Что такое отображение

PUT /myindex/article/1 
{ 
  "post_date": "2018-05-10", 
  "title": "Java", 
  "content": "java is the best language", 
  "author_id": 119
}

PUT /myindex/article/2
{ 
  "post_date": "2018-05-12", 
  "title": "html", 
  "content": "I like html", 
  "author_id": 120
}

PUT /myindex/article/3
{ 
  "post_date": "2018-05-16", 
  "title": "es", 
  "content": "Es is distributed document store", 
  "author_id": 110
}


GET /myindex/article/_search?q=2018-05

GET /myindex/article/_search?q=2018-05-10

GET /myindex/article/_search?q=html

GET /myindex/article/_search?q=java

#查看es自动创建的mapping

GET /myindex/article/_mapping

es автоматически создает индекс, тип и сопоставление (динамическое сопоставление), соответствующие типу

Что такое сопоставление: сопоставление определяет тип данных каждого поля в типе и связанные атрибуты, например, как эти поля сегментированы.

{
  "myindex": {
    "mappings": {
      "article": {
        "properties": {
          "author_id": {
            "type": "long"
          },
          "content": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "post_date": {
            "type": "date"
          },
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

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

Поддерживаемые типы данных:

(1) Основные типы данных

字符型:string,string类型包括
text 和 keyword

text类型被用来索引长文本,在建立索引前会将这些文本进行分词,转化为词的组合,建立索引。允许es来检索这些词语。text类型不能用来排序和聚合。

Keyword类型不需要进行分词,可以被用来检索过滤、排序和聚合。keyword 类型字段只能用本身来进行检索

数字型:long, integer, short, byte, double, float
日期型:date
布尔型:boolean
二进制型:binary

(2) Сложные типы данных (сложные типы данных)

数组类型(Array datatype):数组类型不需要专门指定数组元素的type,例如:
    字符型数组: [ "one", "two" ]
    整型数组:[ 1, 2 ]
    数组型数组:[ 1, [ 2, 3 ]] 等价于[ 1, 2, 3 ]
    对象数组:[ { "name": "Mary", "age": 12 }, { "name": "John", "age": 10 }]
对象类型(Object datatype):_ object _ 用于单个JSON对象;
嵌套类型(Nested datatype):_ nested _ 用于JSON数组;

(3) Геотипы данных

地理坐标类型(Geo-point datatype):_ geo_point _ 用于经纬度坐标;
地理形状类型(Geo-Shape datatype):_ geo_shape _ 用于类似于多边形的复杂形状;

(4) Специализированные типы данных

IPv4 类型(IPv4 datatype):_ ip _ 用于IPv4 地址;
Completion 类型(Completion datatype):_ completion _提供自动补全建议;
Token count 类型(Token count datatype):_ token_count _ 用于统计做了标记的字段的index数目,该值会一直增加,不会因为过滤条件而减少。
mapper-murmur3
类型:通过插件,可以通过 _ murmur3 _ 来计算 index 的 hash 值;
附加类型(Attachment datatype):采用 mapper-attachments
插件,可支持_ attachments _ 索引,例如 Microsoft Office 格式,Open Document 格式,ePub, HTML 等。

Поддерживаемые свойства:

"store":false//Независимо от того, хранится ли это поле отдельно от поля _source, значение по умолчанию равно false, вы можете только искать, но не получать значение

"index": true//Сегментация по словам, без сегментации по словам: false , установите значение false, поле не будет индексироваться

"analyzer":"ik"//Указываем токенизатор, токенизатор по умолчанию - стандартный анализатор

"boost": 1,23//Вес оценки на уровне поля, значение по умолчанию 1,0

"doc_values":false//Для полей not_analyzed они включены по умолчанию, а поля сегментации слов использовать нельзя. Сортировка и агрегирование могут повысить производительность и сэкономить память

"fielddata":{"format":"disabled"}//Для полей сегментации слов это может повысить производительность при участии в сортировке или агрегации. Рекомендуется использовать doc_value независимо от полей сегментации слов

"fields":{"raw":{"type":"string","index":"not_analyzed"}} //Вы можете указать несколько режимов индекса для поля, значение одного и того же поля, токен, не причастие

"ignore_above":100 //Текст длиной более 100 символов будет игнорироваться и не индексироваться

"include_in_all":ture//Установите, включено ли это поле в поле _all, значение по умолчанию равно true, если для индекса не задана опция no

"index_options":"docs"//4 необязательных параметра docs (индексный номер документа), freqs (номер документа + частота слова), position (номер документа + частота слова + позиция, обычно используется для запроса расстояния), offsets (номер документа + Частота слова + позиция + смещение, обычно используется в поле выделения) По умолчанию поле сегментации слова — позиция, а по умолчанию — другие документы

"norms":{"enable":true,"loading":"lazy"}//Конфигурация по умолчанию для поля сегментации слов, без поля сегментации слов: default {"enable":false}, усиление при сохранении коэффициента длины и индекса , рекомендуется Участие в использовании оценочных полей увеличит потребление памяти

"null_value":"NULL"//Установите значение инициализации некоторых отсутствующих полей, можно использовать только строки, а нулевое значение поля сегментации слова также будет сегментацией слова

"position_increament_gap": 0//Влияет на запрос расстояния или приблизительный запрос, его можно установить в поле сегментации слов данных полей с несколькими значениями, а интервал наклона можно указать при запросе, значение по умолчанию 100

"search_analyzer":"ik"//Установить токенизатор при поиске, который по умолчанию такой же, как и анализатор. Например, для индекса используется стандарт+ngram, а для выполнения функции автоматической подсказки при поиске используется стандарт.

"подобие":"BM25"//По умолчанию используется алгоритм TF/IDF, укажите стратегию оценки поля, допустимо только для типа строки и типа сегментации слова

"term_vector":"no"//Векторная информация по умолчанию не сохраняется, поддерживаются параметры yes (термин + позиция), with_positions (терм + позиция), with_offsets (терм + смещение), with_positions_offsets (терм + позиция + смещение) для быстрого выделения Быстрая подсветка векторов может повысить производительность, но ее открытие увеличит объем индекса, что не подходит для больших объемов данных.

Классификация отображений:

(1) Динамическое отображение:

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

Это поведение можно контролировать с помощью динамической настройки, которая принимает следующие параметры:

true:默认值。动态添加字段
false:忽略新字段
strict:如果碰到陌生字段,抛出异常

Динамическую настройку можно применить к корневому объекту или любому полю типа объекта.

POST /lib2

#Создать тип сопоставления для индекса lib2

{

    "settings":{
    
    "number_of_shards" : 3,
    
    "number_of_replicas" : 0
    
    },
    
     "mappings":{
     
      "books":{
      
        "properties":{
        
            "title":{"type":"text"},
            "name":{"type":"text","index":false},
            "publish_date":{"type":"date","index":false},
            
            "price":{"type":"double"},
            
            "number":{"type":"integer"}
        }
      }
     }
}

POST /lib2

#Создать тип сопоставления для индекса lib2

{

    "settings":{
    
    "number_of_shards" : 3,
    
    "number_of_replicas" : 0
    
    },
    
     "mappings":{
     
      "books":{
      
        "properties":{
        
            "title":{"type":"text"},
            "name":{"type":"text","index":false},
            "publish_date":{"type":"date","index":false},
            
            "price":{"type":"double"},
            
            "number":{
                "type":"object",
                "dynamic":true
            }
        }
      }
     }
}

2.7 Базовый запрос (запрос-запрос)

2.7.1 Подготовка данных

PUT /lib3
{
    "settings":{
    "number_of_shards" : 3,
    "number_of_replicas" : 0
    },
     "mappings":{
      "user":{
        "properties":{
            "name": {"type":"text"},
            "address": {"type":"text"},
            "age": {"type":"integer"},
            "interests": {"type":"text"},
            "birthday": {"type":"date"}
        }
      }
     }
}

GET /lib3/user/_search?q=name:lisi

GET /lib3/user/_search?q=name:zhaoliu&sort=age:desc

2.7.2 Запрос терминов и запрос терминов

Запрос термина ищет точный термин в инвертированном индексе, он не знает о существовании токенизатора. Этот вид запроса подходит для ключевого слова, числа, даты.

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

GET /lib3/user/_search/
{
  "query": {
      "term": {"interests": "changge"}
  }
}

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

GET /lib3/user/_search
{
    "query":{
        "terms":{
            "interests": ["hejiu","changge"]
        }
    }
}

2.7.3 Управление количеством, возвращаемым запросом

from: с какого документа начать Размер: необходимое количество

GET /lib3/user/_search
{
    "from":0,
    "size":2,
    "query":{
        "terms":{
            "interests": ["hejiu","changge"]
        }
    }
}

2.7.4 Возврат номера версии

GET /lib3/user/_search
{
    "version":true,
    "query":{
        "terms":{
            "interests": ["hejiu","changge"]
        }
    }
}

2.7.5 запрос соответствия

запрос сопоставления знает о существовании токенизатора, выполняет токенизацию в поле, а затем запрашивает

GET /lib3/user/_search
{
    "query":{
        "match":{
            "name": "zhaoliu"
        }
    }
}
GET /lib3/user/_search
{
    "query":{
        "match":{
            "age": 20
        }
    }
}

match_all: запросить все документы

GET /lib3/user/_search
{
  "query": {
    "match_all": {}
  }
}

multi_match: можно указать несколько полей

GET /lib3/user/_search
{
    "query":{
        "multi_match": {
            "query": "lvyou",
            "fields": ["interests","name"]
         }
    }
}

match_phrase: запрос на совпадение фраз

Механизм ElasticSearch сначала анализирует строку запроса и строит фразовый запрос из анализируемого текста, а это значит, что все причастия во фразе должны совпадать, а относительное положение каждого причастия должно оставаться неизменным:

GET lib3/user/_search
{
  "query":{  
      "match_phrase":{  
         "interests": "duanlian,shuoxiangsheng"
      }
   }
}

2.7.6 Укажите возвращаемые поля

GET /lib3/user/_search
{
    "_source": ["address","name"],
    "query": {
        "match": {
            "interests": "changge"
        }
    }
}

2.7.7 Управление загруженными полями

GET /lib3/user/_search
{
    "query": {
        "match_all": {}
    },
    
    "_source": {
          "includes": ["name","address"],
          "excludes": ["age","birthday"]
      }
}

Используйте подстановочный знак *

GET /lib3/user/_search
{
    "_source": {
          "includes": "addr*",
          "excludes": ["name","bir*"]
        
    },
    "query": {
        "match_all": {}
    }
}

2.7.8 Сортировка

Используйте sort для достижения сортировки: по убыванию: по убыванию, по возрастанию

GET /lib3/user/_search
{
    "query": {
        "match_all": {}
    },
    "sort": [
        {
           "age": {
               "order":"asc"
           }
        }
    ]
        
}

GET /lib3/user/_search
{
    "query": {
        "match_all": {}
    },
    "sort": [
        {
           "age": {
               "order":"desc"
           }
        }
    ]
        
}

2.7.9 Запрос соответствия префикса

GET /lib3/user/_search
{
  "query": {
    "match_phrase_prefix": {
        "name": {
            "query": "zhao"
        }
    }
  }
}

2.7.10 Запрос диапазона

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

Параметры: from, to, include_lower, include_upper, boost

include_lower: включать ли левую границу диапазона, значение по умолчанию — true

include_upper: включать ли правую границу диапазона, значение по умолчанию — true

GET /lib3/user/_search
{
    "query": {
        "range": {
            "birthday": {
                "from": "1990-10-10",
                "to": "2018-05-01"
            }
        }
    }
}


GET /lib3/user/_search
{
    "query": {
        "range": {
            "age": {
                "from": 20,
                "to": 25,
                "include_lower": true,
                "include_upper": false
            }
        }
    }
}

2.7.11 запрос с подстановочными знаками

Подстановочные знаки * и ? разрешены для запросов

* представляет 0 или более символов

? представляет любой символ

GET /lib3/user/_search
{
    "query": {
        "wildcard": {
             "name": "zhao*"
        }
    }
}


GET /lib3/user/_search
{
    "query": {
        "wildcard": {
             "name": "li?i"
        }
    }
}

2.7.12 нечеткий реализует нечеткий запрос.

значение: ключевое слово запроса

boost: вес запроса, значение по умолчанию 1.0

min_similarity: установить минимальное сходство для сопоставления, значение по умолчанию 0,5, для строк значение 0-1 (включая 0 и 1); для числовых значений значение может быть больше 1; для типов даты значение равно 1d, 1m и т.д., 1d означает 1 день

prefix_length: указывает общую длину префикса для различения терминов, по умолчанию 0

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

GET /lib3/user/_search
{
    "query": {
        "fuzzy": {
             "interests": "chagge"
        }
    }
}

GET /lib3/user/_search
{
    "query": {
        "fuzzy": {
             "interests": {
                 "value": "chagge"
             }
        }
    }
}

2.7.13 Выделение результатов поиска

GET /lib3/user/_search
{
    "query":{
        "match":{
            "interests": "changge"
        }
    },
    "highlight": {
        "fields": {
             "interests": {}
        }
    }
}

2.8 Запрос фильтра

Фильтр не вычисляет корреляцию и при этом может кэшироваться. Следовательно, скорость фильтрации выше, чем скорость запроса.

POST /lib4/items/_bulk
{"index": {"_id": 1}}

{"price": 40,"itemID": "ID100123"}

{"index": {"_id": 2}}

{"price": 50,"itemID": "ID100124"}

{"index": {"_id": 3}}

{"price": 25,"itemID": "ID100124"}

{"index": {"_id": 4}}

{"price": 30,"itemID": "ID100125"}

{"index": {"_id": 5}}

{"price": null,"itemID": "ID100127"}

####2.8.1 Простой запрос фильтра

GET /lib4/items/_search
{ 
       "post_filter": {
             "term": {
                 "price": 40
             }
       }
}


GET /lib4/items/_search
{
      "post_filter": {
          "terms": {
                 "price": [25,40]
              }
        }
}

GET /lib4/items/_search
{
    "post_filter": {
        "term": {
            "itemID": "ID100123"
          }
      }
}

Посмотреть результаты анализа токенизатора:

GET /lib4/_mapping

Если вы не хотите, чтобы поле идентификатора продукта было токенизировано, заново создайте сопоставление

DELETE lib4

PUT /lib4
{
    "mappings": {
        "items": {
            "properties": {
                "itemID": {
                    "type": "text",
                    "index": false
                }
            }
        }
    }
}

2.8.2 логический запрос фильтра

Комбинированный запрос фильтра может быть реализован

Формат:

{
    "bool": {
        "must": [],
        "should": [],
        "must_not": []
    }
}

must: условия, которые должны быть выполнены --- и

следует: условия, которые могут или не могут быть выполнены --или

must_not: условия, которые не должны выполняться --not

GET /lib4/items/_search
{
    "post_filter": {
          "bool": {
               "should": [
                    {"term": {"price":25}},
                    {"term": {"itemID": "id100123"}}
                   
                  ],
                "must_not": {
                    "term":{"price": 30}
                   }
                       
                }
             }
}

Вложенное использование bool:

GET /lib4/items/_search
{
    "post_filter": {
          "bool": {
                "should": [
                    {"term": {"itemID": "id100123"}},
                    {
                      "bool": {
                          "must": [
                              {"term": {"itemID": "id100124"}},
                              {"term": {"price": 40}}
                            ]
                          }
                    }
                  ]
                }
            }
}

2.8.3 Фильтрация диапазона

gt: >

lt: <

gte: >=

lte: <=

GET /lib4/items/_search
{
     "post_filter": {
          "range": {
              "price": {
                   "gt": 25,
                   "lt": 50
                }
            }
      }
}

2.8.5 Фильтр не пустой

GET /lib4/items/_search
{
  "query": {
    "bool": {
      "filter": {
          "exists":{
             "field":"price"
         }
      }
    }
  }
}

GET /lib4/items/_search
{
    "query" : {
        "constant_score" : {
            "filter": {
                "exists" : { "field" : "price" }
            }
        }
    }
}

2.8.6 Кэш фильтра

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

Примечание. ElasticSearch не кэширует все фильтры по умолчанию. Следующие фильтры не кэшируются по умолчанию:

numeric_range
script
geo_bbox
geo_distance
geo_distance_range
geo_polygon
geo_shape
and
or
not

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

Открытый метод: добавить после оператора запроса фильтра "_кэш": правда

2.9 Совокупный запрос

(1)sum

GET /lib4/items/_search
{
  "size":0,
  "aggs": {
     "price_of_sum": {
         "sum": {
           "field": "price"
         }
     }
  }
}

(2)min

GET /lib4/items/_search
{
  "size": 0, 
  "aggs": {
     "price_of_min": {
         "min": {
           "field": "price"
         }
     }
  }
}

(3)max

GET /lib4/items/_search
{
  "size": 0, 
  "aggs": {
     "price_of_max": {
         "max": {
           "field": "price"
         }
     }
  }
}

(4)avg

GET /lib4/items/_search
{
  "size":0,
  "aggs": {
     "price_of_avg": {
         "avg": {
           "field": "price"
         }
     }
  }
}

(5) мощность: найти мощность

GET /lib4/items/_search
{
  "size":0,
  "aggs": {
     "price_of_cardi": {
         "cardinality": {
           "field": "price"
         }
     }
  }
}

(6) термины: группировка

GET /lib4/items/_search
{
  "size":0,
  "aggs": {
     "price_group_by": {
         "terms": {
           "field": "price"
         }
     }
  }
}

Группа по возрасту для тех, кто увлекается пением

GET /lib3/user/_search
{
  "query": {
      "match": {
        "interests": "changge"
      }
   },
   "size": 0, 
   "aggs":{
       "age_group_by":{
           "terms": {
             "field": "age",
             "order": {
               "avg_of_age": "desc"
             }
           },
           "aggs": {
             "avg_of_age": {
               "avg": {
                 "field": "age"
               }
             }
           }
       }
   }
}

2.10 Составные запросы

Запрос, который объединяет несколько базовых запросов в один запрос

2.10.1 Запрос с помощью bool

Получает следующие параметры:

должен: Документы должны соответствовать этим условиям, чтобы быть включенными.

не должен: Для включения документы не должны соответствовать этим условиям.

должен: Если какое-либо из этих утверждений выполняется, _score будет увеличен, в противном случае он не будет иметь никакого эффекта. В основном они используются для корректировки оценки релевантности каждого документа.

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

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

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

{
    "bool": {
        "must": { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }},
            { "range": { "date": { "gte": "2014-01-01" }}}
        ]
    }
}

Если оператора must нет, то хотя бы один из них должен совпасть. Однако, если есть хотя бы один оператор must, нет необходимости, чтобы оператор must совпадал. Если мы не хотим влиять на оценку из-за времени документа, мы можем переписать предыдущий пример с оператором фильтра:

{
    "bool": {
        "must": { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "range": { "date": { "gte": "2014-01-01" }} 
        }
    }
}

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

Сам логический запрос также можно использовать как запрос без оценки. Просто поместите его в оператор фильтра и постройте внутри логическую логику:

{
    "bool": {
        "must": { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "bool": { 
              "must": [
                  { "range": { "date": { "gte": "2014-01-01" }}},
                  { "range": { "price": { "lte": 29.99 }}}
              ],
              "must_not": [
                  { "term": { "category": "ebooks" }}
              ]
          }
        }
    }
}

2.10.2 запрос с константной_оценкой

Он применяет инвариантную постоянную оценку ко всем соответствующим документам. Он часто используется, когда вам нужно только выполнить фильтр и никаких других запросов (например, запросов на оценку).

{
    "constant_score":   {
        "filter": {
            "term": { "category": "ebooks" } 
        }
    }
}

Термин запрос помещается в константу_оценку, которая превращается в фильтр без подсчета очков. Этот подход можно использовать для замены логических запросов только оператором фильтра.

Раздел 3 Принцип эластичного поиска

3.1 Распределенная архитектура парсинга es

3.1.1 Прозрачные и скрытые функции распределенной архитектуры

ElasticSearch — это распределенная система, скрывающая сложные механизмы обработки.

Механизм фрагментации: нам все равно, по какому механизму фрагментируются данные и в какой фрагмент они окончательно помещаются.

Копия осколка:

Механизм обнаружения кластера (cluster discovery): Например, сейчас мы запускаем es-процесс, когда запускается второй es-процесс, этот процесс автоматически обнаруживает кластер как узел и присоединяется к нему.

Балансировка нагрузки на сегменты: например, теперь в кластере 10 сегментов и 3 узла, и es будет выполнять сбалансированное распределение, чтобы поддерживать сбалансированный запрос нагрузки для каждого узла.

маршрутизация запросов

3.1.2 Механизм расширения емкости

Вертикальное расширение: покупка новых машин и замена существующих

Горизонтальное расширение: прямое увеличение машины

3.1.3 rebalance

Автоматическая балансировка при добавлении или удалении узлов

3.1.4 главный узел

Основные обязанности главного узла — это вещи, связанные с операциями кластера, такие как создание или удаление индексов, отслеживание того, какие узлы являются частью кластера, и принятие решения о том, какие сегменты назначить соответствующим узлам. Стабильный главный узел очень важен для работоспособности кластера.

3.1.5 Пиринг узлов

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

3.2 Механизм сегментирования и репликации

1. Индекс содержит несколько осколков

2. Каждый шард — это минимальная единица работы, несущая часть данных, каждый шард — это инстанс lucene с полной возможностью построения индексов и обработки запросов

3. При добавлении или удалении узлов шард автоматически распределяет нагрузку между узлами.

4. Для основного сегмента и сегмента реплики каждый документ должен существовать только в определенном основном сегменте и соответствующем сегменте реплики и не может существовать в нескольких основных сегментах.

5. Шард-реплика — это реплика основного шарда, отвечающая за отказоустойчивость и нагрузку запросов на чтение

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

7. Количество основных сегментов по умолчанию — 5, а количество реплик по умолчанию — 1. По умолчанию имеется 10 сегментов, 5 основных сегментов и 5 сегментов реплик.

8. Первичный осколок нельзя размещать на том же узле, что и его собственный осколок реплики (иначе узел выйдет из строя, первичный осколок и реплика будут потеряны, а отказоустойчивость не может быть достигнута), но его можно разместить на тот же узел, что и сегмент реплики других первичных сегментов на узле

3.3 Создание анализа индекса в среде с одним узлом

PUT /myindex
{
   "settings" : {
      "number_of_shards" : 3,
      "number_of_replicas" : 1
   }
}

В это время только 3 первичных сегмента будут выделены только одному узлу, а остальные 3 сегмента реплики не могут быть выделены (реплика-реплика сегмента не может находиться на одном узле). Кластер может нормально работать, но как только нода выходит из строя, все данные теряются, кластер недоступен и не может принимать запросы.

3.4 Создание анализа индекса в среде с двумя узлами

Выделите 3 основных сегмента одному узлу, а остальные 3 сегмента реплики — другому узлу.

Основной сегмент и сегмент реплики синхронизируются.

Как первичный сегмент, так и сегмент реплики могут обрабатывать клиентские запросы на чтение.

3.5 Процесс горизонтального расширения

1. После расширения основной сегмент и сегмент реплики будут автоматически сбалансированы по нагрузке.

2. После расширения количество сегментов на каждом узле будет уменьшено, поэтому ресурсы ЦП, памяти и ввода-вывода, выделенные для каждого сегмента, будут больше, а производительность будет улучшена.

3. Лимит расширения, если есть 6 осколков, то лимит расширения 6 узлов, и в каждом узле по одному осколку.Если вы хотите превысить лимит расширения, например, чтобы расширить до 9 узлов, вы можете увеличить количество осколков реплики

4,6 осколка, 3 узла, какое максимальное количество простоев сервера он может выдержать? (Отказоустойчивость) Любое время простоя сервера приведет к потере некоторых данных

Для повышения отказоустойчивости увеличьте количество шардов: 9 сегментов (3 основных сегмента, 6 реплик), которые могут выдерживать до двух простоев сервера.

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

3.6 Механизм отказоустойчивости ElasticSearch

Возьмем для примера 9 осколков и 3 узла:

1. Если главный узел выходит из строя, не все первичные сегменты в это время находятся в активном состоянии, поэтому состояние кластера в это время отображается красным цветом.

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

Третий шаг обработки отказоустойчивости: перезапустить неисправную машину, новый мастер скопирует все копии на ноду, (синхронизировать изменения, произошедшие после простоя), в это время состояние кластера зеленое, т.к. осколок и осколок реплики имеют активный статус

3.7 Основные метаданные документов

1._index:

Указывает, в каком индексе хранится документ

Похожие документы хранятся в одном индексе (поля документов в основном одинаковые)

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

2._type:

Указывает, к какому типу индекса относится документ

В индексе может быть только один тип

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

3._id:

Уникальный идентификатор документа в сочетании с индексом и типом однозначно идентифицирует документ.

Значение можно указать вручную или сгенерировать с помощью es

3.8 Как сгенерировать идентификатор документа

1. Указать вручную

put /index/type/66

Обычно при импорте существующих данных из других систем в es

2. Сгенерировать значение идентификатора из es

post /index/type

Идентификатор, сгенерированный es, имеет длину 20 символов, использует кодировку base64, безопасен для URL, использует алгоритм GUID и не конфликтует, когда значения идентификатора генерируются одновременно в распределенных условиях.

3.9 Анализ метаданных _source

По сути, это содержимое в теле запроса, когда мы добавляем документ

Укажите, какие поля включены в возвращаемый результат:

get /index/type/1?_source=name

3.10 Анализ принципа изменения содержания документа

Способ замены:

PUT /lib/user/4
{ "first_name" : "Jane",

"last_name" :   "Lucy",

"age" :         24,

"about" :       "I like to collect rock albums",

"interests":  [ "music" ]
}

Способ модификации (частичное обновление):

POST /lib/user/2/_update
{
    "doc":{
       "age":26
     }
}

Удалить документ: помечен как удаленный, по мере увеличения объема данных es удалит его в подходящее время.

3.11 Выполнение частичного обновления на основе скрипта groovy

es имеет встроенную поддержку сценариев, которая может выполнять сложные операции на основе groovy-скриптов.

1. Изменить возраст

POST /lib/user/4/_update
{
  "script": "ctx._source.age+=1"
}

2. Измените имя

POST /lib/user/4/_update
{
  "script": "ctx._source.last_name+='hehe'"
}

3. Добавьте хобби

POST /lib/user/4/_update
{
  "script": {
    "source": "ctx._source.interests.add(params.tag)",
    "params": {
      "tag":"picture"
    }
  }
}

4. Удалить хобби

POST /lib/user/4/_update
{
  "script": {
    "source": "ctx._source.interests.remove(ctx._source.interests.indexOf(params.tag))",
    "params": {
      "tag":"picture"
    }
  }
}

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

POST /lib/user/4/_update
{
  "script": {
    "source": "ctx.op=ctx._source.age==params.count?'delete':'none'",
    "params": {
        "count":29
    }
  }
}

6.upsert

POST /lib/user/4/_update
{
  "script": "ctx._source.age += 1",
  
  "upsert": {
     "first_name" : "Jane",
     "last_name" :   "Lucy",
     "age" :  20,
     "about" :       "I like to collect rock albums",
     "interests":  [ "music" ]
  }
}

3.12 частичное обновление обрабатывает конфликты параллелизма.

Используется оптимистическая блокировка: _version

retry_on_conflict:

POST /lib/user/4/_update?retry_on_conflict=3

Повторно получать данные документа и информацию о версии для обновления и непрерывной работы Максимальное количество операций равно значению retry_on_conflict.

3.13 Анализ принципа маршрутизации данных документа

1. Документ направляется на шард:

Индекс состоит из нескольких сегментов. При добавлении (удалении, изменении) документа es должен решить, на каком сегменте документ хранится. Этот процесс называется маршрутизацией данных.

2. Алгоритм маршрутизации:

 shard=hash(routing) % number_of_pirmary_shards

Пример: один индекс, 3 первичных осколка

(1) Каждый раз, когда вы добавляете, удаляете, изменяете и проверяете значение маршрутизации, по умолчанию используется значение _id документа.

(2) Используйте хеш-функцию для вычисления этого значения маршрутизации.

(3) Расчетное значение и количество первичных осколков принимают остаток

Остаток должен быть между 0---(number_of_pirmary_shards-1), и документ находится на соответствующем осколке

Значение маршрутизации по умолчанию равно значению _id документа. Вы также можете указать значение вручную. Ручное указание полезно для балансировки нагрузки и повышения производительности пакетного чтения.

3. После определения количества первичных осколков его нельзя изменить.

3.14 Внутренний принцип добавления, удаления и изменения документа

1: При отправке CRUD-запроса можно выбрать любой узел, и узел становится координирующим узлом

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

3. Узел координатора отвечает клиенту

3.15 Принцип согласованности записи и механизм кворума

1. Любые операции добавления, удаления и изменения могут выполняться с параметром последовательность

Значения, которые можно указать для этого параметра:

один: (основной сегмент) может выполняться, пока активен один основной сегмент

all: (все сегменты) Все первичные сегменты и фрагменты реплик активны для выполнения.

кворум: (по умолчанию) значение по умолчанию, большинство сегментов активны для выполнения (например, всего имеется 6 сегментов, и как минимум 3 сегмента активны для выполнения операций записи)

2. механизм кворума: доступно большинство осколков,

int((primary+number_of_replica)/2)+1

Например: 3 основных сегмента, 1 реплика.

int((3+1)/2)+1=3

По крайней мере, 3 шарда активны

Примечание. Могут быть случаи, когда сегмент не может быть полностью выделен.

Например: 1 основной осколок, 1 реплика. интервал((1+1)/2)+1=2 Но если есть только один узел, поскольку первичный осколок и осколок реплики не могут быть на одном узле, операция записи все равно не может быть выполнена.

Другой пример: 1 основной шард, 3 реплики, 2 узла.

int((1+3)/2)+1=3

Наконец: когда количество активных осколков не соответствует требованиям, es будет ждать одну минуту по умолчанию.Если количество активных осколков не увеличится в течение периода ожидания, будет отображаться тайм-аут

put /index/type/id?timeout=60s

3.16 Внутренние принципы запроса документов

Шаг 1: Запрос запроса отправляется на любой узел, и этот узел становится координирующим узлом.Узел использует алгоритм маршрутизации для вычисления основного сегмента, в котором находится документ.

Шаг 2. Координирующий узел перенаправляет запрос в основной сегмент или в сегмент реплики (с помощью алгоритма циклического планирования запросы равномерно распределяются между основным сегментом и сегментом реплики).

Шаг 3: Узел, обрабатывающий запрос, возвращает результат координирующему узлу, а координирующий узел возвращает его приложению.

Особый случай: запрошенный документ все еще находится в процессе индексации, первичный шард существует, но шар-реплика не существует, но запрос перенаправляется в шард-реплику, и отображается сообщение о том, что документ не найден

3.17 Разбор массовых операций в формате JSON

массовый формат:

{action:{metadata}}\n

{requstbody}\n

Почему бы не использовать следующий формат:

[{

"action": {

},

"data": {

}

}]

Этот метод читаем, но внутренняя обработка вызывает затруднения:

1. Чтобы преобразовать массив json в объект JSONArray, в памяти должна быть копия текста json и объект JSONArray.

2. Разберите каждый json в массиве json и направьте документ в каждом запросе.

3. Создайте массив запросов для нескольких запросов, направляемых на один и тот же сегмент.

4. Сериализовать этот массив запросов

5. Отправьте сериализованный массив запросов на соответствующий узел.

Потребляйте больше памяти и увеличивайте накладные расходы виртуальной машины Java.

1. Не нужно преобразовывать его в json-объект, вырезать json напрямую в соответствии с новой строкой, копия json-текста не требуется в памяти.

2. Для каждых двух наборов json прочитайте мета и выполните маршрутизацию документов

3. Отправьте соответствующий json непосредственно на узел

3.18 Анализ результатов запроса

{
  "took": 419,
  "timed_out": false,
  "_shards": {
    "total": 3,
    "successful": 3,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 0.6931472,
    "hits": [
      {
        "_index": "lib3",
        "_type": "user",
        "_id": "3",
        "_score": 0.6931472,
        "_source": {
          "address": "bei jing hai dian qu qing he zhen",
          "name": "lisi"
        }
      },
      {
        "_index": "lib3",
        "_type": "user",
        "_id": "2",
        "_score": 0.47000363,
        "_source": {
          "address": "bei jing hai dian qu qing he zhen",
          "name": "zhaoming"
        }
      }

take: время, потраченное на запрос, в миллисекундах

_shards: сколько шардов запрошено всего

total: общее количество запрошенных документов

max_score: В этом запросе максимальное значение оценки релевантности, чем выше соответствие между документом и этим запросом, чем больше значение _score, тем выше рейтинг.

hits: запрос по умолчанию для первых 10 документов

время вышло:

GET /lib3/user/_search?timeout=10ms
{
    "_source": ["address","name"],
    "query": {
        "match": {
            "interests": "changge"
        }
    }
}

3.19 Многоиндексный, многотипный режим запроса

GET _search

GET /lib/_search

GET /lib,lib3/_search

GET /*3,*4/_search

GET /lib/user/_search

GET /lib,lib4/user,items/_search

GET /_all/_search

GET /_all/user,items/_search

3.20 Проблема глубокого пейджинга в запросе пейджинга

GET /lib3/user/_search
{
    "from":0,
    "size":2,
    "query":{
        "terms":{
            "interests": ["hejiu","changge"]
        }
    }
}

GET /_search?from=0&size=3

Глубокое пейджинг: запрос очень глубокий. Например, индекс имеет три первичных сегмента, каждый из которых хранит 6000 фрагментов данных. Мы хотим получить данные на 100-й странице (10 фрагментов на странице), что называется глубоким пейджингом. .

Как получить 10 штук данных на странице 100?

Ищите 10 фрагментов данных от 990 до 999 в каждом осколке, а затем используйте эти 30 фрагментов данных для сортировки.После сортировки 10 фрагментов данных являются данными для поиска.Этот подход неверен, потому что данные в 3 осколки _ баллы разные.Может быть оценка _score первого фрагмента данных в одном шарде выше, чем 1000-й фрагмент данных в другом шарде, поэтому способ поиска 10 фрагментов данных от 990 до 999 в каждом шарде и тогда сортировка неверна.

Правильный способ — искать все элементы данных от 0 до 999 для каждого осколка (в порядке сортировки), а затем возвращать их все в узел координат. 100, а затем вернуться к клиенту.

проблемы с производительностью глубокого пейджинга

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

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

3. Координатному узлу, потребляющему ЦП, необходимо отсортировать возвращаемые данные.Этот процесс сортировки потребляет много ЦП.

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

3.21 строка запроса: запрос и анализ copy_to

GET /lib3/user/_search?q=interests:changge

GET /lib3/user/_search?q=+interests:changge

GET /lib3/user/_search?q=-interests:changge

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

Примечание. Тип поля, на которое указывает copy_to, должен быть: текст.

Если поле не указано, оно будет запрашиваться из поля copy_to.

GET /lib3/user/_search?q=changge

3.22 Проблема сортировки строк

Сортировка по полю строкового типа обычно неточна, поскольку оно разбито на несколько терминов.

Решение: проиндексируйте поле дважды, один раз с сегментацией слов (для поиска) и один раз без сегментации слов (для сортировки).

GET /lib3/_search

GET /lib3/user/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "interests": {
        "order": "desc"
      }
    }
  ]
}

GET /lib3/user/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "interests.raw": {
        "order": "asc"
      }
    }
  ]
}

DELETE lib3

PUT /lib3
{
    "settings":{
        "number_of_shards" : 3,
        "number_of_replicas" : 0
      },
     "mappings":{
      "user":{
        "properties":{
            "name": {"type":"text"},
            "address": {"type":"text"},
            "age": {"type":"integer"},
            "birthday": {"type":"date"},
            "interests": {
                "type":"text",
                "fields": {
                  "raw":{
                     "type": "keyword"
                   }
                },
                "fielddata": true
             }
          }
        }
     }
}

3.23 Как рассчитать показатель релевантности

Использование алгоритма TF/IDF (частота терминов и обратная частота документов)

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

搜索内容: hello world

Hello,I love china.

Hello world,how are you!

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

搜索内容:hello world

hello,what are you doing?

I like the world.

hello 在索引的所有文档中出现了500次,world出现了100次

3. Норма длины поля (уменьшение длины поля): чем длиннее поле, тем ниже корреляция

Искать: привет мир

{"title":"hello,what's your name?","content":{"owieurowieuolsdjflk"}}

{"title":"hi,good morning","content":{"lkjkljkj.......world"}}

Посмотрите, как рассчитывается оценка:

GET /lib3/user/_search?explain=true
{
    "query":{
        "match":{
            "interests": "duanlian,changge"
        }
    }
}

Посмотрите, соответствует ли документ запросу:

GET /lib3/user/2/_explain
{
    "query":{
        "match":{
            "interests": "duanlian,changge"
        }
    }
}

3.24 Парсинг значений документа

DocValues ​​на самом деле означает, что когда Lucene строит инвертированный индекс, он дополнительно строит упорядоченный положительный индекс (на основе списка сопоставления документа => значение поля)

{"birthday":"1985-11-11",age:23}

{"birthday":"1989-11-11",age:29}

document     age       birthday

doc1         23         1985-11-11

doc2         29         1989-11-11

Хранится на диске, экономя память

Сортировка, группировка и некоторые операции агрегирования могут значительно повысить производительность.

Примечание. По умолчанию поле без сегментации слов включено и недействительно для полей сегментации слов (данные поля должны быть установлены в значение true)

PUT /lib3
{
    "settings":{
    "number_of_shards" : 3,
    "number_of_replicas" : 0
    },
     "mappings":{
      "user":{
        "properties":{
            "name": {"type":"text"},
            "address": {"type":"text"},
            "age": {
              "type":"integer",
              "doc_values":false
            },
            "interests": {"type":"text"},
            "birthday": {"type":"date"}
        }
      }
     }
}

3.25 Прокрутка поиска большого объема данных на основе технологии прокрутки

Если, например, 100 000 единиц данных должны быть проверены за один раз, производительность будет очень низкой.В настоящее время обычно используется скользящий запрос с прокруткой, пакет за пакетом, пока не будут запрошены все данные.

1. Сколл-поиск сохранит снимок представления на момент первого поиска, а затем предоставит поиск данных только на основе старого снимка представления.Если данные изменятся в течение этого периода, они не будут видны пользователю

2. Метод сортировки по _doc (без _score) имеет более высокую производительность

3. Каждый раз, когда отправляется запрос на прокрутку, нам также необходимо указать параметр scoll и временное окно, каждый поисковый запрос может быть выполнен в течение этого временного окна.

GET /lib3/user/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "sort":["_doc"],
  "size":3
}

GET /_search/scroll
{
   "scroll": "1m",
   "scroll_id": "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAAAAdFkEwRENOVTdnUUJPWVZUd1p2WE5hV2cAAAAAAAAAHhZBMERDTlU3Z1FCT1lWVHdadlhOYVdnAAAAAAAAAB8WQTBEQ05VN2dRQk9ZVlR3WnZYTmFXZw=="
}

3.26 стратегия динамического отображения.

dynamic:

1.true: динамическое сопоставление при обнаружении незнакомых полей

2.false: игнорировать незнакомые поля

3.strict: при назначении встречи на незнакомом поле будет сообщено об ошибке.

PUT /lib8
{
    "settings":{
    "number_of_shards" : 3,
    "number_of_replicas" : 0
    },
     "mappings":{
      "user":{
        "dynamic":strict,
        "properties":{
            "name": {"type":"text"},
            "address":{
                "type":"object",
                "dynamic":true
            },
        }
      }
     }
}

#会报错

PUT  /lib8/user/1
{
  "name":"lisi",
  "age":20,
  "address":{
    "province":"beijing",
    "city":"beijing"
  }
}

date_detection: По умолчанию дата будет распознаваться в определенном формате, например, гггг-ММ-дд.

Вы можете вручную отключить определенный тип date_detection

PUT /lib8
{
    "settings":{
    "number_of_shards" : 3,
    "number_of_replicas" : 0
    },
     "mappings":{
      "user":{
        "date_detection": false,
        }
    }
}

Настроить шаблон динамического сопоставления (тип)

PUT /my_index
{ 
  "mappings": { 
    "my_type": { 
      "dynamic_templates": [ 
        { 
          "en": { 
            "match": "*_en", 
            "match_mapping_type": "string", 
            "mapping": { 
              "type": "text", 
              "analyzer": "english" 
            } 
          } 
        } 
      ] 
     } 
  } 
}
#使用了模板

PUT /my_index/my_type/3
{
  "title_en": "this is my dog"
  
}
#没有使用模板

PUT /my_index/my_type/5
{
  "title": "this is my cat"
}

GET my_index/my_type/_search
{
  "query": {
    "match": {
      "title": "is"
    }
  }
}

3.27 Перестроить индексы

Настройка поля не может быть изменена. Если вы хотите изменить поле, вам следует повторно создать индекс в соответствии с новым сопоставлением, затем запросить данные в пакетах и ​​повторно записать их в индекс с помощью массового API.

При пакетных запросах рекомендуется использовать API-интерфейс прокрутки и переиндексировать данные в многопоточном параллельном режиме.Каждый раз при прокрутке вы можете запросить фрагмент данных в указанную дату и передать его потоку. .

PUT /index1/type1/4
{
   "content":"1990-12-12"
}

GET /index1/type1/_search

GET /index1/type1/_mapping



#报错
PUT /index1/type1/4
{
   "content":"I am very happy."
}

#Изменить тип содержимого на строковый, сообщается об ошибке, модификация не разрешена

PUT /index1/_mapping/type1
{
  "properties": {
    "content":{
      "type": "text"
    }
  }
}

# Создайте новый индекс, запросите данные в индексе index1 и импортируйте их в новый индекс #Но приложение использует предыдущий индекс, чтобы не перезапускать приложение, присвойте индексу index1 #псевдоним

PUT /index1/_alias/index2

#Создать новый индекс и изменить тип содержимого на строку

PUT /newindex
{
  "mappings": {
    "type1":{
      "properties": {
        "content":{
          "type": "text"
        }
      }
    }
  }
}

#Использовать пакетный запрос прокрутки

GET /index1/type1/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "sort": ["_doc"],
  "size": 2
}

#Используйте массовое написание новых индексов в пакетном режиме

POST /_bulk
{"index":{"_index":"newindex","_type":"type1","_id":1}}
{"content":"1982-12-12"}

# Свяжите псевдоним index2 с новым индексом, приложение не нужно перезапускать

POST /_aliases
{
  "actions": [
    {"remove": {"index":"index1","alias":"index2"}},
    {"add": {"index": "newindex","alias": "index2"}}
]
}

GET index2/type1/_search

3.28 Причины, по которым индексы неизменяемы

К инвертированным индексам относятся:

Список документов, количество документов, количество раз термина в каждом документе, где он встречается, длина каждого документа, средняя длина всех документов

Причина, по которой индекс не меняется:

Отсутствие необходимости в блокировках, повышение производительности параллелизма

всегда можно хранить в кеше (фильтр)

Экономьте ресурсы процессора и ввода-вывода

Раздел 4 Доступ к ElasticSearch в приложениях Java

4.1 Реализация документов запросов в приложениях Java

Добавьте зависимость ElasticSearch6.2.4 к pom:

<dependencies>
    <dependency>
      <groupId>org.elasticsearch.client</groupId>
      <artifactId>transport</artifactId>
      <version>6.2.4</version>
    </dependency>    
    
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  
  </dependencies> 
  
  <build>
      <plugins>
			<!-- java编译插件 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
  </build>

4.2 Реализовать добавление документов в Java-приложения

        "{" +
                "\"id\":\"1\"," +
                "\"title\":\"Java设计模式之装饰模式\"," +
                "\"content\":\"在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。\"," +
                "\"postdate\":\"2018-05-20 14:38:00\"," +
                "\"url\":\"csdn.net/79239072\"" +
        "}"
        
 XContentBuilder doc1 = XContentFactory.jsonBuilder()
                    .startObject()
                    .field("id","3")
                    .field("title","Java设计模式之单例模式")
                    .field("content","枚举单例模式可以防反射攻击。")
                    .field("postdate","2018-02-03")
                    .field("url","csdn.net/79247746")
                    .endObject();
        
        IndexResponse response = client.prepareIndex("index1", "blog", null)
                .setSource(doc1)
                .get();
        
		System.out.println(response.status());

4.3 Реализация удаления документов в приложении Java

DeleteResponse response=client.prepareDelete("index1","blog","SzYJjWMBjSAutsuLRP_P").get();

//删除成功返回OK,否则返回NOT_FOUND

System.out.println(response.status());

4.4 Реализация документов обновления в Java-приложениях

UpdateRequest request=new UpdateRequest();
        request.index("index1")
                .type("blog")
                .id("2")
                .doc(
                		XContentFactory.jsonBuilder().startObject()
                        .field("title","单例模式解读")
                        .endObject()
                );
UpdateResponse response=client.update(request).get();

//更新成功返回OK,否则返回NOT_FOUND

System.out.println(response.status());

upsert方式:

IndexRequest request1 =new IndexRequest("index1","blog","3")
                .source(
                		XContentFactory.jsonBuilder().startObject()
                                .field("id","3")
                                .field("title","装饰模式")
                                .field("content","动态地扩展一个对象的功能")
                                .field("postdate","2018-05-23")
                                .field("url","csdn.net/79239072")
                                .endObject()
                );
        UpdateRequest request2=new UpdateRequest("index1","blog","3")
                .doc(
                		XContentFactory.jsonBuilder().startObject()
                        .field("title","装饰模式解读")
                        .endObject()
                ).upsert(request1);
        
UpdateResponse response=client.update(request2).get();
        
//upsert操作成功返回OK,否则返回NOT_FOUND

System.out.println(response.status());

4.5 Реализация пакетных операций в Java-приложениях

MultiGetResponse mgResponse = client.prepareMultiGet()
	                .add("index1","blog","3","2")
	                .add("lib3","user","1","2","3")
	                .get();
		    
for(MultiGetItemResponse response:mgResponse){
	            GetResponse rp=response.getResponse();
	            if(rp!=null && rp.isExists()){
	                System.out.println(rp.getSourceAsString());
	            }
	        }
	        
bulk:

BulkRequestBuilder bulkRequest = client.prepareBulk();

bulkRequest.add(client.prepareIndex("lib2", "books", "4")
                .setSource(XContentFactory.jsonBuilder()
                        .startObject()
                        .field("title", "python")
                        .field("price", 68)
                        .endObject()
                )
        );
bulkRequest.add(client.prepareIndex("lib2", "books", "5")
                .setSource(XContentFactory.jsonBuilder()
                        .startObject()
                        .field("title", "VR")
                        .field("price", 38)
                        .endObject()
                )
        );
        //批量执行
BulkResponse bulkResponse = bulkRequest.get();
        
System.out.println(bulkResponse.status());
if (bulkResponse.hasFailures()) { 
            System.out.println("存在失败操作");
        }