Reference description
This article refers to the video and articles of crazy God saying crazy God. You can support crazy God( Crazy God ElasticSearch article address,Crazy God ElasticSearch video address)
Version Description
This article involves the software and version statement (the following download addresses are all domestic Huawei images except ik)
Software | edition |
---|---|
elasticSearch | 7.6.1 |
elasticSearch-head-master | 7.6.1 |
kibana | 7.6.1 |
elasticsearch-analysis-ik1 | 7.6.1 |
jdk | 8 (minimum) |
Source code of this article
The source code of this article is put on the gitee warehouse, address
1, springboot integrates and connects Es for basic operations
Create a springboot project
Process omission
Import dependency
Note that because elasticSearch involves version issues, you should pay attention to the custom version dependency (you can use the jar package of any version of es, which is specified below)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.es</groupId> <artifactId>elasticSearch_api</artifactId> <version>0.0.1-SNAPSHOT</version> <name>elasticSearch_api</name> <description>elasticSearch_api</description> <properties> <java.version>1.8</java.version> <!--Custom version dependency--> <elasticsearch.version>7.6.1</elasticsearch.version> </properties> <dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
Write an advanced client configuration class
package cn.es.config; import org.apache.http.HttpHost; import org.elasticsearch.client.Node; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * elasticSearch to configure */ //spring like xml @Configuration public class ESConfig { /*<bean id=restHighLevelClient class="org.elasticsearch.client.RestHighLevelClient">*/ //Inject an advanced client @Bean public RestHighLevelClient restHighLevelClient(){ RestHighLevelClient restHighLevelClient=new RestHighLevelClient(RestClient.builder(new HttpHost("localhost",9200,"http"))); return restHighLevelClient; } }
In this way, the advanced client is injected into the bean container. Later, you can use the advanced client to operate es.
Create an entity class for testing
package cn.es.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * elastic Entity classes used in the test */ @Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private int age; }
Write configuration file
Since my es is local and no password is set, it does not need to be configured. What needs to be configured can be configured in application.yml (properties)
Test class
The directory structure is as follows:
Because of the problem of bean container, please use the default test package of springboot to test to prevent bean injection.
The test classes are as follows:
package cn.es; import cn.es.pojo.User; import com.alibaba.fastjson.JSON; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.TermQueryBuilder; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.FetchSourceContext; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.io.IOException; import java.util.ArrayList; import java.util.concurrent.TimeUnit; /** * An index can be considered a "database" * Type can be regarded as "table" * A document can be seen as "data in a library (rows in a table)" */ @SpringBootTest class ElasticSearchApiApplicationTests { @Autowired RestHighLevelClient client; @Test void contextLoads() { } //1, Create index @Test void createIndex() throws IOException { //1 / request to create a new index (Library) CreateIndexRequest createIndexRequest= new CreateIndexRequest("blog_demo"); // createIndexRequest //2. Execute request and get response CreateIndexResponse createIndexResponse= client.indices().create(createIndexRequest, RequestOptions.DEFAULT); System.out.println(createIndexResponse); } //2, Get index @Test void getIndex() throws IOException { //1 / request to create a new index (Library) GetIndexRequest request= new GetIndexRequest("blog_demo"); //2. Determine whether the index exists boolean flag_exist= client.indices().exists(request,RequestOptions.DEFAULT); System.out.println(flag_exist); } //3, Delete index @Test void deleteIndex() throws IOException { //1 / request to create a new index (Library) DeleteIndexRequest request= new DeleteIndexRequest("blog_demo"); //2. Determine whether the index exists AcknowledgedResponse response= client.indices().delete(request,RequestOptions.DEFAULT); System.out.println(response.isAcknowledged()); } //4, Insert document (row in table) first insert, second overwrite update @Test void addDocument() throws IOException { User user=new User(1,"Xiao Ming",18); //1. Create request IndexRequest indexRequest= new IndexRequest("blog_demo"); //3. Rules //id can not be specified because es provides a default generation strategy. If it needs to be specified, you need to pay attention to whether the id is repeated. Once it is repeated, the previous data will be overwritten indexRequest.id(String.valueOf(user.getId())); indexRequest.timeout(TimeValue.timeValueSeconds(1)); indexRequest.timeout("1s"); //We put the data into the request json format indexRequest.source(JSON.toJSONString(user), XContentType.JSON); //client poke request IndexResponse response= client.index(indexRequest,RequestOptions.DEFAULT); System.out.println(response.toString()); System.out.println(response.status()); } //Get the document and judge whether the document exists @Test void existDocument() throws IOException { GetRequest getRequest=new GetRequest("blog_demo","1"); //Do not return source context getRequest.fetchSourceContext(new FetchSourceContext(false)); getRequest.storedFields("_none_"); boolean flag=client.existsSource(getRequest,RequestOptions.DEFAULT); System.out.println(flag); } //Get the document get the document content get the specified document according to the id @Test void getDocument() throws IOException { GetRequest getRequest=new GetRequest("blog_demo","1"); GetResponse getResponse =client.get(getRequest,RequestOptions.DEFAULT); System.out.println(getResponse.toString()); System.out.println(getResponse.getSourceAsString());//Print the contents of the document } //Update the document record update the document content, keep the original value for the null attribute value, and update the non null attribute value @Test void updateDocument() throws IOException { User user=new User(1,null,81); UpdateRequest request=new UpdateRequest("blog_demo","1"); request.timeout("1s"); //We put the data into the request json format request.doc(JSON.toJSONString(user), XContentType.JSON); UpdateResponse updateResponse =client.update(request,RequestOptions.DEFAULT); System.out.println(updateResponse.toString()); } //Delete document deletes the specified document according to the document id @Test void deleteDocument() throws IOException { DeleteRequest request=new DeleteRequest("blog_demo","1"); request.timeout("1s"); DeleteResponse deleteResponse =client.delete(request,RequestOptions.DEFAULT); System.out.println(deleteResponse.toString()); } //Mass insert data for real projects @Test void insertBulkRequest() throws IOException { BulkRequest request=new BulkRequest(); request.timeout("10s"); ArrayList<User> arrayList=new ArrayList<>(); arrayList.add(new User(10,"zs",18)); arrayList.add(new User(11,"lisi",21)); arrayList.add(new User(12,"ww",16)); arrayList.add(new User(13,"zl",15)); arrayList.add(new User(14,"hh",16)); arrayList.add(new User(15,"ll",14)); for (User user : arrayList) { request.add( new IndexRequest("blog_demo") .id(String.valueOf(user.getId())) .source(JSON.toJSONString(user),XContentType.JSON)); } BulkResponse response= client.bulk(request,RequestOptions.DEFAULT); System.out.println(response.hasFailures()); } /** * query * SearchRequest Search request * SearchSourceBuilder Conditional construction * * @throws IOException */ @Test //query void searchRequest() throws IOException { SearchRequest searchRequest=new SearchRequest("blog_demo"); //Build search criteria SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //Exact matching of query criteria TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "zs"); searchSourceBuilder.query(termQueryBuilder); searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); searchRequest.source(searchSourceBuilder); //Execute query and return results SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); System.out.println(JSON.toJSONString(response.getHits())); System.out.println("-----------------------"); for (SearchHit hit : response.getHits().getHits()) { System.out.println(hit.getSourceAsMap()); } } }
2, Write jd global search examples
I originally wanted to write an example of global search like jd, but due to a hurry, I didn't find a suitable template, so I directly used postman to test. Please ignore the lack of front-end pages
Create project
The creation process is omitted
Import jar package
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.es</groupId> <artifactId>elasticSearch_jd</artifactId> <version>0.0.1-SNAPSHOT</version> <name>elasticSearch_jd</name> <description>elasticSearch_jd</description> <properties> <java.version>1.8</java.version> <!--Custom version dependency--> <elasticsearch.version>7.6.1</elasticsearch.version> </properties> <dependencies> <!--Parsing web pages--> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.10.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>compile</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
Because you want to use jsoup to crawl the commodity data on jd, you need the jar package of jsoup
Encapsulate a tool class to grab jd's commodity data
package cn.es.util; import cn.es.pojo.Content; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; public class HtmlParseUtil { public static void main(String[] args) throws IOException { System.out.println(HtmlParseUtil.getList("Huawei")); // String keyword=""; } public static List<Content> getList(String keyword) throws IOException { //Get request String url = "https://search.jd.com/Search?keyword="+keyword; //Parsing web pages Document document = Jsoup.parse(new URL(url), 30000); Element element = document.getElementById("J_goodsList"); // System.out.println(element.html()); Elements elements = document.getElementsByTag("li"); List<Content> contents=new ArrayList<>(); int i=0; for (Element el:elements){ if (el.attr("class").equalsIgnoreCase("gl-item")) { String img = el.getElementsByTag("img").eq(0).attr("data-lazy-img"); String price = el.getElementsByClass("p-price").eq(0).text(); String title = el.getElementsByClass("p-name").eq(0).text(); // System.out.println("============================"); // System.out.println(img); // System.out.println(price); // System.out.println(title); contents.add(new Content(++i,title,img,price)); } } // System.out.println(contents); return contents; } }
If you want to grab other web pages, you can modify the page address and the relationship between the front-end tags according to your own needs
Encapsulates a tool class for an es operation
package cn.es.util; import ch.qos.logback.core.net.SyslogOutputStream; import cn.es.pojo.Content; import com.alibaba.fastjson.JSON; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.common.text.Text; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.TermQueryBuilder; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestParam; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /** * elasticSearch Tool class */ public class EsUtil { /** * Create an index to determine whether the index exists. If it exists, it returns true. If it does not exist, it is created * If the creation is successful, return true * @return * @throws IOException */ public static boolean createIndex(RestHighLevelClient client,String index) throws IOException { //1. Request to get query index (Library) GetIndexRequest request= new GetIndexRequest(index); //2. Determine whether the index exists boolean flag_exist= client.indices().exists(request,RequestOptions.DEFAULT); if (flag_exist){ //Returns true if the index exists return true; } //If it does not exist, the index is created //3. Request to create a new index (Library) CreateIndexRequest createIndexRequest= new CreateIndexRequest(index); //4. Execute request and get response CreateIndexResponse createIndexResponse= client.indices().create(createIndexRequest, RequestOptions.DEFAULT); return createIndexResponse.isAcknowledged(); } /** * Obtain data from JD's web page and insert elasticSearch data in batches * @param key key Is the keyword to search jd * @param index Index library * @return * @throws IOException */ public static boolean insertListEs(RestHighLevelClient client,String key,String index) throws IOException { //1. Create bulk data insert request BulkRequest request = new BulkRequest(); //2. Set timeout request.timeout("10s"); //3. Grab data from JD's web page and encapsulate it as an entity class collection List<Content> contents = HtmlParseUtil.getList(key); //4. Determine whether the index exists if (createIndex(client,index)) { // If not, create it and use it if necessary //5. The index exists at this time. Insert data into the index for (Content content : contents) { request.add( new IndexRequest(index) // . id(String.valueOf(content.getId())) # duplicate id will overwrite the previous data. Because it is not queried from the database and there is no unique primary key id, the id is not specified temporarily .source(JSON.toJSONString(content), XContentType.JSON)); } BulkResponse response = client.bulk(request, RequestOptions.DEFAULT); return !response.hasFailures(); } return false; } /** * Search the commodity information with the title key in es according to the key keyword (modify the field title according to your own needs) * @param client Advanced client es * @param index Indexes * @param key key word * @param pageNum Pagination page number * @param pageSize Number of pages per page * @return * @throws IOException */ public static List<Map<String,Object>> searchEs(RestHighLevelClient client,String index,String key,int pageNum,int pageSize) throws IOException { List<Map<String,Object>> list=new ArrayList<>(); //1. Conditional search parameter index SearchRequest searchRequest=new SearchRequest(index); //2. Build search criteria SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //3. Pagination int begin=(pageNum-1)*pageSize; searchSourceBuilder.from(begin); searchSourceBuilder.size(pageSize); //4. Query criteria full text search MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", key); //5. Injection execution query criteria searchSourceBuilder.query(matchQueryBuilder); //6. Set query timeout searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); //7. Execute query and return results searchRequest.source(searchSourceBuilder); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); System.out.println(response); for (SearchHit hit : response.getHits().getHits()) { //Traverse query results System.out.println(hit.getSourceAsMap()); Map<String, Object> map = hit.getSourceAsMap(); System.out.println(map); list.add(map); } //Return results return list; } /** * Basically the same as the above functions, the highlight function is added * @param client * @param index * @param key * @param pageNum * @param pageSize * @return * @throws IOException */ public static List<Map<String,Object>> searchEsHighlight(RestHighLevelClient client,String index,String key,int pageNum,int pageSize) throws IOException { List<Map<String,Object>> list=new ArrayList<>(); //1. Conditional search parameter index SearchRequest searchRequest=new SearchRequest(index); //2. Build search criteria SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //3. Pagination int begin=(pageNum-1)*pageSize; searchSourceBuilder.from(begin); searchSourceBuilder.size(pageSize); //4. Query criteria full text search MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", key); //Highlight HighlightBuilder highlightBuilder=new HighlightBuilder(); highlightBuilder.field("title"); //Prefix suffix highlightBuilder.preTags("<p class='light' style='color:red'>"); highlightBuilder.postTags("</p>"); searchSourceBuilder.highlighter(highlightBuilder); highlightBuilder.requireFieldMatch(false);//Only one highlight is displayed for a document //5. Injection execution query criteria searchSourceBuilder.query(matchQueryBuilder); //6. Set query timeout searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); //7. Execute query and return results searchRequest.source(searchSourceBuilder); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); for (SearchHit hit : response.getHits().getHits()) { //Traverse query results Map<String, HighlightField> highlightFields = hit.getHighlightFields(); HighlightField title = highlightFields.get("title"); Map<String, Object> map = hit.getSourceAsMap();//Original results //Resolve the highlighted field and replace the previously highlighted field with the currently highlighted field if (title!=null){ Text[] fragments = title.fragments(); String newTitle=""; for (Text fragment : fragments) { newTitle+=fragment; } hit.getSourceAsMap().put("title",newTitle); } list.add(map); } //Return results return list; } }
Write controller
package cn.es.controller; import cn.es.util.EsUtil; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.util.List; import java.util.Map; /** * elasticSearch Controller for */ @RestController public class EsController { @Autowired RestHighLevelClient client; String index="jd_index"; /** * Search jd's product information according to keywords and insert it into our specified index library * @param key * @return */ @GetMapping("/insertEs/{key}") public Boolean insertEs(@PathVariable String key){ Boolean flag=false; try { flag= EsUtil.insertListEs(client,key,index); } catch (IOException e) { e.printStackTrace(); } return flag; } /** * Query the commodity information in the index library according to the keyword key (without highlighting) * @param key * @param pageNum * @param pageSize * @return * @throws IOException */ @GetMapping("/searchEs/{key}/{pageNum}/{pageSize}") public List<Map<String,Object>> searchEs(@PathVariable String key, @PathVariable int pageNum, @PathVariable int pageSize) throws IOException { List<Map<String,Object>> list=EsUtil.searchEs(client,index,key,pageNum,pageSize); //Return results return list; } /** * Query the commodity information in the index library according to the keyword key (with highlight) * @param key * @param pageNum * @param pageSize * @return * @throws IOException */ @GetMapping("/searchEsHighlight/{key}/{pageNum}/{pageSize}") public List<Map<String,Object>> searchEsHighlight(@PathVariable String key, @PathVariable int pageNum, @PathVariable int pageSize) throws IOException { List<Map<String,Object>> list=EsUtil.searchEsHighlight(client,index,key,pageNum,pageSize); //Return results return list; } }
Write startup class
Pay attention to the annotation of the scanning servlet component
package cn.es; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; @SpringBootApplication @ServletComponentScan public class ElasticSearchJdApplication { public static void main(String[] args) { SpringApplication.run(ElasticSearchJdApplication.class, args); } }
3, Testing
Start the project
Test insert data
Grab the data of the specified keyword from the jd web page to the index library, as follows:
Send request:
View data
Everything ok
Query data (not highlighted)
Send the request as follows:
Query data (highlight)
Send request:
There are many specific query logic, highlighting rules and highlighting styles, which can be expanded!!!
End of this article!!!