preface
ElasticSearch6.8.4: poetry search ver 1.0
Suitable for students with a certain ES foundation, just say HighLevelClient function implementation.
Environment configuration: Docker (ElasticSearch6.8.4+Kibana6.8.4+IK descriptor) +SpringBoot 2.2.13.RELEASE + MySQL5.7 + MyBatis + Redis To control extended dictionaries and disabled dictionaries)
show
The source code
Gitee.com/ven1ce/elas…
How does it work?
Change the database account password in application.yml
Create the ES database and create the POEM table in it
create table poem
(
id bigint auto_increment
primary key,
no varchar(255) not null,
title varchar(100) not null,
author varchar(10) not null,
content varchar(500) not null,
type tinyint default 0 null comment 'Four quatrains of poetry types',
author_detail varchar(500) not null,
source varchar(50) default 'network' not null comment 'source',
create_time datetime null,
update_time datetime null.constraint no
unique (no)
)
comment 'poetry' charset = utf8mb4;
Copy the code
Configure the elasticSearch address
Configuration index
PUT /es
{
"mappings": {
"poem":{
"properties":{
"id":{
"type":"keyword"
},
"no":{
"type":"keyword"
},
"title":{
"type":"text",
"analyzer":"ik_max_word"
},
"author":{
"type":"text",
"analyzer":"ik_max_word"
},
"content":{
"type":"text",
"analyzer":"ik_max_word"
},
"type":{
"type":"integer"
},
"authorDetail":{
"type":"text",
"analyzer":"ik_max_word"
},
"source":{
"type":"keyword"
},
"createTime":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss"
},
"updateTime":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss"
}
}
}
}
}
Copy the code
Start the front end, NPM Run serve
RestHighLevelClient operation
– ElasticSearch upgrade was pretty fast, I couldn’t find a good article online, I didn’t know what to do with RestHighLevelClient Fortunately, the official website document is still detailed, and indeed it is the best official document, although not comprehensive enough, but slowly grinding can come down. so
It is recommended to read the official English document directly.
It is recommended to read the official English document directly.
It is recommended to read the official English document directly.
Important things to say three times, no matter what version 6.x or 7.x you are, do not look for other articles on the web (only as a reference for the comprehensive approach)!
Afraid of some students can not find, I will directly help you to paste the following, pay attention to the version of the same.
ElasticSearch Rest Client
ElasticSearch Official Documentation
Generate ES documents for all data in the database
The first reaction of this feature is the batch processing method of ES, let’s look at the official documentation of ES.
Of course we can also add other requests to the batch request
The website also has additional configurable information and how to synchronize (asynchronous) requests, so check it out for your own needs.
A synchronous request is used here, first fetching all the data in the database (as a case, not a spritz), then generating a new index request from the database data and adding it to the batch. Then highLevelClient initiates the request, obtains the bulkResponse of the returned data of the batch, and processes it.
Code:
/** * Generate es document for all database data */
@Override
public void insertEsAllDate(a) throws IOException {
List<Poem> poems = poemMapper.queryAll();
BulkRequest bulkRequest = new BulkRequest();
for (Poem poem : poems) {
String s = JSON.toJSONString(poem);
bulkRequest.add(new IndexRequest("es"."poem",poem.getNo()).source(s, XContentType.JSON));
}
BulkResponse bulkResponse = highLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
if (bulkResponse.hasFailures()){
for(BulkItemResponse item : bulkResponse.getItems()) { System.out.println(item.getFailureMessage()); }}}Copy the code
Clear all documents in ES
Looking at the documentation, we can see that there is a delete-by-query operation. Literally delete based on the query. So if we want to achieve the operation of clearing the document, then just need to query all, and then delete according to the query.
So how do we get query all documents, look at the official search document and you can see the demonstration already given.
This is slightly different from the documentation. Same idea.
Code:
/** * clear the table with 'es' index */
@Override
public void clearEsAllDate(a) throws IOException {
DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest("es");
deleteByQueryRequest.setQuery(new MatchAllQueryBuilder());
deleteByQueryRequest.setConflicts("proceed");// Version conflicts do not abort the process
highLevelClient.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
}
Copy the code
Paging document retrieval
Go straight to the search document
Set the sourceBuilder form and size attributes to page query. We can also set the timeout.
With the sourceBuilder set up, we can pass it on to the search request. Next, deal with the return value.
Code:
/** * get all es files */
@Override
public List<Poem> getAllEs(a) throws IOException {
List<Poem> result = new ArrayList<>();
SearchRequest searchRequest = new SearchRequest("es");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchAllQuery());
sourceBuilder.from(0);
sourceBuilder.size(10);
searchRequest.source(sourceBuilder);
SearchResponse search = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = search.getHits();
SearchHit[] hits = searchHits.getHits();
if( hits ! =null&& hits.length ! =0) {for(SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString(); Poem poem = JSON.parseObject(sourceAsString, Poem.class); result.add(poem); }}return result;
}
Copy the code
Highlighting the search
Query for Highlighting requests in official documents
We first set up SearchSourceBuilder and HighlightBuilder.
Filed is the highlighted field in HighlightBuilder, and preTags and postTags are the HTML for our highlighted field.
Set up multiple field searches using boolQuery. Configure the priority boost (the bigger the higher the priority) and the word segmentation.
// Set the search field
sourceBuilder.query(QueryBuilders.boolQuery()
.should(QueryBuilders.multiMatchQuery(searchString,"title").boost(4).analyzer("ik_smart"))
.should(QueryBuilders.multiMatchQuery(searchString,"author").boost(3).analyzer("ik_smart"))
.should(QueryBuilders.multiMatchQuery(searchString,"content").boost(2).analyzer("ik_smart"))
.should(QueryBuilders.multiMatchQuery(searchString,"authorDetail").boost(1).analyzer("ik_smart")));Copy the code
We can get the highlighted fields separately from the results. Because the highlighted field String is distinguished from the attributes in the entity. Here you need to think about how to put highlighted strings into entity attributes. So since properties are constantly changing, we can’t write a dead-end program, so think of the set method that uses reflection to get the entity class. Use the set method to inject an attribute with a highlighted label.
// Get the highlighted field setting entity
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
//s is the name of the entity field
for (String s : highlightFields.keySet()) {
HighlightField highlightField = highlightFields.get(s);
Text[] fragments = highlightField.getFragments();
// Gets the attributes of the highlighted field
StringBuilder sb = new StringBuilder();
for (Text fragment : fragments) {
sb.append(fragment.toString());
}
// We use reflection to get the set method because we don't know which attribute it is
try{
Class<? extends Poem> aClass = poem.getClass();
// Convert fields to hump format in accordance with the set method naming convention
String formatString = StringUtils.convertToCamelCase(s);
// Get the method by its name
Method declaredMethod = aClass.getDeclaredMethod("set" + formatString,String.class);
// Execute the method to inject the highlighted label
declaredMethod.invoke(poem,sb.toString());
} catch(NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); }}Copy the code
Code:
/** ** highlight search **@paramSearchString searchString *@returnResults the * /
@Override
public List<Poem> search(String searchString) throws IOException {
// Todo adds redis hot words to the list
// Search for es first
SearchRequest searchRequest = new SearchRequest("es");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// Set the highlight
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title");
highlightBuilder.field("author");
highlightBuilder.field("content");
highlightBuilder.field("authorDetail");
highlightBuilder.preTags("<em style=\"color:red\" >");
highlightBuilder.postTags("</em>");
sourceBuilder.highlighter(highlightBuilder);
// Set the search field
sourceBuilder.query(QueryBuilders.boolQuery()
.should(QueryBuilders.multiMatchQuery(searchString,"title").boost(4).analyzer("ik_smart"))
.should(QueryBuilders.multiMatchQuery(searchString,"author").boost(3).analyzer("ik_smart"))
.should(QueryBuilders.multiMatchQuery(searchString,"content").boost(2).analyzer("ik_smart"))
.should(QueryBuilders.multiMatchQuery(searchString,"authorDetail").boost(1).analyzer("ik_smart"))); searchRequest.source(sourceBuilder);// Get the result
SearchResponse search = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = search.getHits();
SearchHit[] hits = searchHits.getHits();
List<Poem> result = new ArrayList<>();
if(hits ! =null&& hits.length ! =0) {for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
// Convert to entity class
Poem poem = JSON.parseObject(sourceAsString, Poem.class);
// Get the highlighted field setting entity
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
for (String s : highlightFields.keySet()) {
HighlightField highlightField = highlightFields.get(s);
Text[] fragments = highlightField.getFragments();
StringBuilder sb = new StringBuilder();
for (Text fragment : fragments) {
sb.append(fragment.toString());
}
// We use reflection to get the set method because we don't know which attribute it is
try{
Class<? extends Poem> aClass = poem.getClass();
// Convert to hump format to capitalize the first letter
String formatString = StringUtils.convertToCamelCase(s);
Method declaredMethod = aClass.getDeclaredMethod("set" + formatString,String.class);
declaredMethod.invoke(poem,sb.toString());
} catch(NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { e.printStackTrace(); } } result.add(poem); }}// Todo searches the database if it misses
// Add es to todo
return result;
}
Copy the code
conclusion
This is just a brief note of the general operations in learning ES, and most of them are also very simple. At present, there are many target functions that have not been realized. Recently, I have been busy, so I have to put down and do other things for the time being. Come back and try again sometime.
But having said that, I’m going to say it here
It is recommended to read the official English document directly!
Recommend to read the official English document directly!!
Recommend to read the official English document directly!!