Недавно у блоггера была работа с эластичным поиском, поэтому обновление было немного медленным. Теперь я научу вас, как быстро начать работу, и приведу примеры некоторых основных запросов и требований к обновлению. Без лишних слов, давайте начнем:
1. Начните быстро с ES
es download: [https://elasticsearch.cn/download/]() Вот практически все ссылки, необходимые для es, которые можно быстро загрузить и использовать. После того как вы распаковали архив, Elasticsearch готов к работе.
1 cd elasticsearch-<version> 2 ./bin/elasticsearch
Порт es по умолчанию — 9200; транспортный порт — 9300; транспортный порт в основном используется для операций Java-клиента. После успешного запуска мы установим инструменты для работы с es на интерфейсе kibana. Вы также можете скачать шапку. интерфейс кибаны более дружелюбен, и наконец-то развернут ELK. Этот инструмент тоже иногда нужен, поэтому блоггер напрямую установил кибану.
Загрузка Kibana: [https://elasticsearch.cn/download/]() — это та же ссылка, что и es. После загрузки разархивируйте и отредактируйте файл kibana.yml в каталоге конфигурации. Основная конфигурация выглядит следующим образом:
1 server.port: 15601
1 server.host: "0.0.0.0"
1 elasticsearch.hosts: ["http://localhost:9200"]
Вам нужно только изменить эти конфигурации. Предполагается, что версия kibana должна быть такой же, как версия es. В противном случае будет много ошибок, и запуск завершится неудачей. Вы не сможете использовать пользователя root для запуска Linux. Вы должны добавить личного пользователя самостоятельно, команда следующая:
Добавить пользователя: 1 пользовательдобавить testuser
Установить пароль: 1 passwd testuser
Измените права пользователя нашей папки, иначе при запуске всегда будет выдавать сообщение об отсутствии прав: 1 chown -R testuser:testuser kibana
Теперь войдите в нашу папку kibana и запустите kibana от имени пользователя test: 1 /bin/kibana
Адрес доступа: http://localhost:15601
Когда вы это увидите, все в порядке, и мы наконец можем начать использовать es.
Я не буду рассказывать, для чего используется es. В es используется концепция шардирования, которая делится на первичные сегменты и сегменты-реплики. После того, как при создании индекса настроены сегменты-реплики, их должно быть больше или равно двум. Все машины имеют es, и взаимодействие между es необходимо изменить в файле конфигурации. В противном случае, если он не настроен, это всегда будет одна машина, и при построении индекса необходимо тщательно учитывать основной сегмент. Основной сегмент, потому что если вам понадобится изменить основной сегмент в будущем, вы должны заново создать индекс. Если вы добавите или уменьшите основной сегмент, он изменится, когда ES сохранит данные в сегменте, но сегмент реплики будет изменен. отличается, потому что это избыточность данных. Как только основной сегмент выйдет из строя, реплика будет выбрана в качестве основного сегмента, и для этого требуется существование основного сегмента. Роль реплики не имеет значения. реплика предназначена для улучшения пропускной способности данных. Хорошо, давайте начнем настоящий бой:
Нажмите кнопку Dev Tools в Kibana, чтобы написать на панели инструкции для управления индексом:
Создать индекс: шарды первичные шарды реплики Количество настроек реплики шардов зависит от того, сколько у вас машин — 1
PUT /test
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
},
"mappings": {
"_doc": {
"properties": {
"name": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"age": {
"type":"integer"
}
}
}
}
}
Установите сопоставления и убедитесь, что тип поля правильный, и используйте токенизатор в текстовом типе. Не используйте токенизатор по умолчанию, который делит каждый китайский символ на один. Запрашивать его в принципе бесполезно. , который можно скачать, выполнив поиск в Интернете.
Каждый, кто посещал курсы китайского языка, знает, что в предложениях есть проблемы с двусмысленностью. Например, «Мост через реку Янцзы в Ухане» можно разбить на «Мэр Уханя», «Город Ухань», «Мост через реку Янцзы», поэтому его разделяет сегментатор слов; ключевой термин запроса Word, полное совпадение, Запрос сегментатора слов не соответствует. В дополнение к ним есть также синонимы на китайском языке, такие как яблоко и iPhone. Когда люди ищут, они в основном вводят яблоко, но в результате получается iPhone, и фруктов очень мало. Это потому, что вы также можете выполнять запросы синонимов. Однако вам необходимо настроить файл синонимов. Конкретную операцию можно решить самостоятельно в режиме онлайн. Главное — использовать текстовый файл, который вы отредактировали в конфигурации, при создании индекса. В файле есть синонимы, которые вы хотите использовать, например. : iPhone, мобильный телефон Apple;
Теперь давайте займемся фактической разработкой. Я использую ElasticsearchRestTemplate для разработки. Этот класс в основном охватывает большинство запросов на разработку требований. Начнем с примера:
Поисковый запрос:
1 String[] includes = new String[] {
2 "paperBaseId"
3 ,"auditInfoStatus"
4 };
5 SourceFilter sourceFilter = new FetchSourceFilterBuilder().withIncludes(includes).build();
6 SearchQuery searchQuery = new NativeSearchQueryBuilder()
7 .withSourceFilter(sourceFilter)
8 // Добавить условия запроса
9 .withQuery(QueryBuilders.termsQuery("paperBaseId",paperBaseId))
10 .build();
11 List<EsPaperBase> esPaperBaseList = elasticsearchRestTemplate.queryForList(searchQuery,EsPaperBase.class);
1 //Обновление сопоставления одного индекса
2 Map<String, Object> params = new HashMap<String, Object>();
3 params.put("flag", deleteFlag);
4 //ctx._source — это сам индекс
5 String code = "ctx._source.deleteFlag=params.flag;";
6 ScriptType type = ScriptType.INLINE;
7 //Используем скрипт для обновления значений полей
8 Script script = new Script(type, Script.DEFAULT_SCRIPT_LANG, code, params);
9
10 UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest();
11 updateByQueryRequest.indices("exam_information");//Установим индекс
12 updateByQueryRequest.setDocTypes("doc");//Установить документы и исправить документ
13 updateByQueryRequest.setQuery(QueryBuilders.termsQuery("paperBaseId", paperBaseId));//Установить запрос
14 updateByQueryRequest.setScript(script);//Если есть скрипт, добавляем его
15 updateByQueryRequest.setConflicts("proceed"); // Продолжить, если настройки конфликтуют с версией
16 updateByQueryRequest.setRefresh(true);//После завершения запроса вызовем и обновим написанный нами индекс
17 this.elasticsearchTemplate.getClient().updateByQuery(updateByQueryRequest, RequestOptions.DEFAULT);//Обновить
1 //Пакетное обновление с множественным индексом
2 Map<String,Object> updateMap = new HashMap<>();
3 updateMap.put("deleteFlag",deleteFlag);
4 updateMap.put("lastUpdateTime",currDatetime);
5 UpdateRequest doc = new UpdateRequest().doc(updateMap);
6 List<UpdateQuery> updateQuerys = new ArrayList<>();
7 //Генерируем операции пакетного обновления
8 paperBaseId.stream().forEach(id ->{
9 UpdateQuery build = new UpdateQueryBuilder()
10 .withUpdateRequest(doc)
11 .withDoUpsert(true)
12 .withIndexName("paper_base")
13 .withType("doc")
14 .withId(id).build();
15 updateQuerys.add(build);
16 });
17 elasticsearchTemplate.bulkUpdate(updateQuerys,BulkOptions.builder().withRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).build());
18
1 //Операция запроса
2 MatchQueryBuilder lastUpdateUser = QueryBuilders.matchQuery("personId", userId);
3 MatchQueryBuilder deleteflag = QueryBuilders.matchQuery("deleteFlag", BaseEntity.DEL_FLAG_DELETE);
4 //Создаем логический запрос с несколькими условиями
5 BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
6 BoolQueryBuilder mustQuery = boolQueryBuilder.must(lastUpdateUser).must(deleteflag);
7 //Вложенный индекс, вам нужно использовать вложенный запрос
8 mustQuery.must(QueryBuilders.nestedQuery("entityNodes", QueryBuilders.termQuery("entityNodes.node_type", recyclePaperDTO.getNodeType()), ScoreMode.None));
9 //Вы можете использовать запрос, это не обязательное условие
10 BoolQueryBuilder nodeQueryBuilder = QueryBuilders.boolQuery();
11 nodeQueryBuilder.should(QueryBuilders.nestedQuery("entityNodes", QueryBuilders.wildcardQuery("entityNodes.parent_ids", "*," + recyclePaperDTO.getNodeId() + "*"), ScoreMode.None));
12 nodeQueryBuilder.should(......);
13 mustQuery.must(nodeQueryBuilder);
14 //Запрос использует сортировку
15 SortBuilder order = new FieldSortBuilder("lastUpdateTime").order(SortOrder.DESC);
16 //Вы можете использовать подсветку, которая представляет собой html-тег
17 HighlightBuilder highlightBuilder = new HighlightBuilder();
18 highlightBuilder.preTags("<span class='highlighted'>")
19 .postTags(</span>)
20 .field("paperBaseName");//Какое поле выделено
21 //Используем пейджинговый запрос
22 SearchQuery nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
23 .withQuery(mustQuery).withSort(order).withHighlightBuilder(highlightBuilder)
24 .withPageable(PageRequest.of(recyclePaperDTO.getPageNum()-1, recyclePaperDTO.getPageSize())).build();
25 //Выполнить запрос. Вы также можете использовать объектentMapper по умолчанию. EsPaperBase.class — это класс запроса, который необходимо сопоставить самостоятельно.
26 elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder, EsPaperBase.class, new HighlightResultMapper(entityMapper));
27
1 @Data
2 @Builder
3 @NoArgsConstructor
4 @AllArgsConstructor
5 @Document(indexName = "paper_base", type = "doc")
6 @Setting(settingPath = "/elasticsearch/settings.json")//Вы можете установить первичные сегменты, фрагменты реплик, установить стоп-слова по умолчанию и т. д.
7 public class EsPaperBase {
8
9 @Id
10 @Field(type = FieldType.Keyword, name = "paperBaseId")
11 private String paperBaseId;
12
13 /**
14 * Название экзаменационной работы
15 */
16 @MultiField(mainField = @Field(type = FieldType.Text, analyzer = "standard" , name = "paperBaseName"),
17 otherFields = {
18 @InnerField(suffix = "zh", type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart"),
19 @InnerField(suffix = "en", type = FieldType.Text, analyzer = "english"),
20 })
21 private String paperBaseName;
22
23 /**
24 * Имена общих уровней можно запрашивать с помощью средств разбиения по словам и нечеткого сопоставления.
25 */
26 @Field(type = FieldType.Text, name = "shareLevelName")
27 private String shareLevelName;
28
29
30 /**
31 * Создатель, не может использовать сегментатор слов для запроса точного соответствия.
32 */
33 @Field(type = FieldType.Keyword, name = "personId")
34 private String personId;
35
36
37 /**
38 * время создания
39 */
40 @Field(type = FieldType.Date, name = "createtime", format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")
41 private String createtime;
42
43 /**
44 * Время обновления
45 */
46 @Field(type = FieldType.Date, name = "lastUpdateTime", format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")
47 private String lastUpdateTime;
48
49 /**
50 * удалить идентификатор 0: не удалено, 1: удалено
51 */
52 @Field(type = FieldType.Keyword, name = "deleteFlag")
53 private String deleteFlag;
54 /**
55 * Рекомендации по тестированию, встроенные поля
56 */
57 @Field(type=FieldType.Nested,name="paperRecommends")
58 private List<EsPaperRecommend> paperRecommends;
59
60 ......
61 }
1 {//setting.json
2 "index": {
3 "number_of_shards": "5",
4 "number_of_replicas": "2",
5 "refresh_interval": "1s",
6 "max_rescore_window": 10000000
7 },
8 "analysis": {
9 "filter": {
10 "spanish_stop": {
11 "type": "stop",
12 "stopwords": [ "si", "esta", "el", "la" ]
13 },
14 "light_spanish": {
15 "type": "stemmer",
16 "language": "light_spanish"
17 }
18 },
19 "analyzer": {
20 "my_spanish": {
21 "tokenizer": "spanish",
22 "filter": [ //Порядок важен
23 "lowercase",
24 "asciifolding",
25 "spanish_stop",
26 "light_spanish"
27 ]
28 }
29 }
30 }
31 }
В настоящее время многие компании в основном используют приложения с распределенной архитектурой. Каждый прикладной модуль компании имеет несколько машин, и возникает проблема чтения логов. Наш самый глупый метод — открыть фон каждого сервера для просмотра, что на данный момент неэффективно. можно использовать es, kibana, logstash или для краткости ELK; Ознакомьтесь с системой распределенного журнала, но в этой статье для демонстрации не будет устанавливаться logstash. Поскольку нам нужно только выполнить запрос журнала, мы можем использовать вариант EFK ELK, а filebeat может выполнять облегченный сбор журналов. Самое главное — увидеть, как. мы делаем это, настраиваем, а затем используем Kibana для запроса журналов.
После установки logstash разархивируйте и создайте в конфигурации новый my-logstash.conf. Обратите внимание на три основных блока в этой конфигурации: ввод, фильтр и вывод — это файл журнала с суффиксом .log, который используется для поглощения. logs, а filter — это конфигурация фильтрации, независимо от того, в какой elasticsearch импортируются выходные данные, следующая конфигурация:
1 input {
2 file {
3 type => "log"
4 path => ["/apps/svr/server/*/log.file"]
5 start_position => "end"
6 ignore_older => 0
7 codec=> multiline {
8 pattern => "^\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}"
9 negate => true
10 auto_flush_interval => 5
11 what => "previous"
12 }
13 }
14 beats {
15 port => 5044
16 }
17 }
18 output {
19 if [type] == "log" {
20 elasticsearch {
21 hosts => ["http://127.0.0.1:19200"]
22 index => "logstash-%{+YYYY.MM}"
23 #user => es
24 #password => es2018
25 }
26 }
27 }
Если вы настраиваете его самостоятельно, лучше всего ввести его вручную, а не копировать и вставлять. Очень вероятно, что специальные символы появятся и вызовут сбой при запуске команды запуска: ./bin/logstah -f my-logstash.conf.
Наконец, мы можем использовать Kibana для запроса журналов. На этом всё, что касается простых базовых приложений, с базовыми приложениями в работе проблем нет;