Elasticearch 整合SpringBoot

169 阅读10分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

承接上文: Elasticearch 搜索引擎

Boot 整合 Elasticearch

在这里插入图片描述

  • 普普通通来个Boot 工程:集成Elasticearch
  • 依赖,配置,各种api对象操作使用!

Elasticearch依赖配置:

pom.xml

     <dependencies>
 <!-- Elasticsearch高级客户端。内部提供api 方法可以直接完成一些 http请求的调用,只需要输入对应参数即可,内部自动完成 -->
         <dependency>
             <groupId>org.elasticsearch.client</groupId>
             <artifactId>elasticsearch-rest-high-level-client</artifactId>
             <version>6.5.4</version>
         </dependency>
 <!-- Elasticsearch 的依赖jar -->
         <dependency>
             <groupId>org.elasticsearch</groupId>
             <artifactId>elasticsearch</artifactId>
             <version>6.5.4</version>                <!-- 版本! -->
         </dependency>
     </dependencies>

配置文件 .yml

application.yml

 #yml 配置定义自己的Elasticearch 启动服务运行端口;
 my:
   es:
     host: 127.0.0.1:9200    #集群环境可以使用 ,xxx.x.x.x:9200,xxx.x.x.x:9200 来表示;

Elasticearch的配置类:

  • 对Elasticearch 集群ip端口的控制:

EsConfig

 import org.apache.http.HttpHost;
 import org.elasticsearch.client.RestClient;
 import org.elasticsearch.client.RestHighLevelClient;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 ​
 @Configuration
 public class EsConfig {
 ​
     @Value("${my.es.host}")       //@Value() 获取.yml 中配置后面方便,集群操作!
     private String hostList;
 ​
 ​
     @Bean                        //创建RESTful 的请求客户端对象, @Bean注入到SPring容器中!
     public RestHighLevelClient client() {
         //拆分hostList 逗号, 获得集群的ip集群数组!
         String[] hostStr = hostList.split(",");
         //创建HttpHost数组,其中存放es主机和端口的配置信息
         HttpHost[] httpHosts = new HttpHost[hostStr.length];
         //循环遍历: 0获取第一参数ip   1第二个参数 端口!
         for (int i = 0; i < hostStr.length; i++) {
             String str = hostStr[i];
             httpHosts[i] = new HttpHost(str.split(":")[0], Integer.parseInt(str.split(":")[1]), "http");
         }
         //存放在RestHighLevelClient,管理集群的ip 端口;
         return new RestHighLevelClient(RestClient.builder(httpHosts));
     }
 }

主程序类:

TestRun.Java

 import com.wsm.service.EsService;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.ConfigurableApplicationContext;
 ​
 @SpringBootApplication  //Boot的启动注解
 public class TestRun {
     public static void main(String[] args) throws Exception {
         //Boot,启动入口
         ConfigurableApplicationContext run = SpringApplication.run(TestRun.class, args);
         
         //通过run 起运行对象,获取到Spring容器中的对象!必须使用run来获取,不然直接new 会null pointer!
         //EsService 来源于Service层的实际代码操作!
         EsService es  = run.getBean(EsService.class);   
         es.deleteIndex();   //删除索引库!
     }
 }

正片开始:EsService

上面只是基本的环境搭建的简单配置, 下面才是Elasticearch 的关键代码部分:

基本,增删改 案例:


删除索引库

  • Delete 请求: http://localhost:9200/索引 直接删除索引

EsService.Java

 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
 import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.support.master.AcknowledgedResponse;
 import org.elasticsearch.client.RequestOptions;
 import org.elasticsearch.client.RestHighLevelClient;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.SearchHits;
 import org.elasticsearch.search.builder.SearchSourceBuilder;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import java.util.HashMap;
 import java.util.Map;
 ​
 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
     
     //删除索引请求
     public void deleteIndex() throws Exception {
         //DeleteIndexRequest()方法参数: 要删除的索引名,返回一个删除索引请求对象;
         DeleteIndexRequest request = new DeleteIndexRequest("wsm");
         //client的方法执行删除,参数: 删除索引请求对象 RequestOptions.DEFAULT   返回一个Response响应对象;
         AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
         //返回结果true/false 失败/成功!
         System.out.println(delete.isAcknowledged());
     }
 }

主程序测试:

  • 控制台返回:true/false

创建索引库/映射

6.0之后一个索引对应一个映射so: 建索引同时加映射;

  • 创建索引库put请求 http://localhost:9200/索引库名称 需要设置分片/配置
  • 创建映射 post http://localhost:9200/索引库名称/映射名称(类型,表)/_mapping 指定映射名,JSON的所需参数

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
     
     //创建索引库,6.0之后一个索引对应一个映射so: 建索引同时加映射;
     public void createIndex() throws Exception {
         //创建索引请求对象————指定索引名
         CreateIndexRequest request = new CreateIndexRequest("wsm");
         //指定分片/备份
         request.settings(Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0"));
         //设置映射————类型名,fieid及属性类型...,JSON形式传输
         request.mapping("doc", "{\n" +
                 "\t"properties": {\n" +
                 "\t\t"description": {\n" +
                 "\t\t\t"type": "text",\n" +
                 "\t\t\t"analyzer": "ik_max_word",\n" +
                 "\t\t\t"search_analyzer": "ik_smart"\n" +
                 "\t\t},\n" +
                 "\t\t"name": {\n" +
                 "\t\t\t"type": "text",\n" +
                 "\t\t\t"analyzer": "ik_max_word",\n" +
                 "\t\t\t"search_analyzer": "ik_smart"\n" +
                 "\t\t},\n" +
                 "\t\t"pic": {\n" +
                 "\t\t\t"type": "text",\n" +
                 "\t\t\t"index": false\n" +
                 "\t\t},\n" +
                 "\t\t"price": {\n" +
                 "\t\t\t"type": "float"\n" +
                 "\t\t},\n" +
                 "\t\t"studymodel": {\n" +
                 "\t\t\t"type": "keyword"\n" +
                 "\t\t},\n" +
                 "\t\t"timestamp": {\n" +
                 "\t\t\t"type": "date",\n" +
                 "\t\t\t"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"\n" +
                 "\t\t}\n" +
                 "\t}\n" +
                 "}", XContentType.JSON);
         //clientindices().create执行创建!—————— 请求参数,DEFAULT.
         CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
         //获取创建结果:boolean
         boolean acknowledged = createIndexResponse.isAcknowledged();
         System.out.println(acknowledged);
     }
 }

主程序测试:

  • 控制台返回:truePostaman get查看创建成功!在这里插入图片描述

添加文档 / 根据id修改文档

  • post 或 put 请求: http://localhost:9200/索引名/映射名/id值 传入JSON 参数形式,赋值生成一个Document 如果不指定id值ES会自动生成一个唯一ID 添加后的文档,再次执行,指定id 就可以直接修改数据了!

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
     
     //新增文档! 添加数据!
     public void addDoc() throws Exception {
         //创建一个map类型存储要存储的数据,准备json数据
         Map<String, Object> jsonMap = new HashMap<>();
         jsonMap.put("name", "spring cloud实战");
         jsonMap.put("description", "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud基础入门 3.实战Spring Boot 4.注册中心eureka。");
         jsonMap.put("studymodel", "201001");
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         jsonMap.put("timestamp", dateFormat.format(new Date()));
         jsonMap.put("price", 5.6f);
         //索引请求对象————索引名,映射名,id(这里没有添加,相同的id会修改覆盖之前的文档数据!)
         IndexRequest request = new IndexRequest("wsm", "doc");
         //索引请求对象:内部会转换成JSON
         request.source(jsonMap); //存储参数数据,Object类型,这里是Map
         //索引响应对象
         IndexResponse response = client.index(request, RequestOptions.DEFAULT);
         //获取响应结果
         DocWriteResponse.Result result = response.getResult();
         System.out.println(result);
     }
 }

主程序测试:

  • Get请求: http://localhost:9200/索引名/映射名/id值http://localhost:9200/索引名/映射名/_search 查询所有数据! 在这里插入图片描述
  • id, 不指定默认提供!

id 查看文档数据

  • Get请求: http://localhost:9200/索引名/映射名/id值

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     //根据 id查询文档数据!
     public void getInfo() throws Exception {
         //根据索引名,文档名,id值: 获取文档数据
         GetRequest request = new GetRequest("wsm", "doc", "W8Q3FngBedCFzRwGU3V0");
         GetResponse response = client.get(request, RequestOptions.DEFAULT);
         System.out.println(response.isExists());                        //isExists() 响应中是否存在数据!
         Map<String, Object> sourceAsMap = response.getSourceAsMap();    //返回Map对象,直接输出打印
         System.out.println(sourceAsMap);
     }
 }

主程序测试:

  • 控制台输出数据! 在这里插入图片描述

更新文档值

  • post请求: http://localhost:9200/索引名/映射/修改文档id/_update
 {
    "doc" : {
       "修改Fieid" : "修改值..."
    }
 }

在这里插入图片描述

  • 修改成功: _version版本+1; EsService.Java
 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     //更新文档
     public void update() throws Exception {
         //指定 索引 映射 更新_id
         UpdateRequest request = new UpdateRequest("wsm", "doc", "XcRgFngBedCFzRwGanV-");
         //要更新的值
         Map<String, Object> jsonMap = new HashMap<>();
         jsonMap.put("name", "spring boot实战");
         //要更新的值存入请求对象中;
         request.doc(jsonMap);
         //更新
         UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
         System.out.println(update.status());
     }
 }

主程序测试:

  • 控制台不报错,返回ok
  • Postman get查看数据: 在这里插入图片描述
  • 值更改!中间出了个意味,重新增了个数据id 重新生成了

常用查询案例:

前言:

  • 搜索引擎最关键的就是要搜索结果,因此要有强大的查询能力!
  • 为了方便操作,学习,下面一个操作案例资源:

准备环境

  • 创建xc_course索引库 Put请求 http://localhost:9200/xc_course 别忘了分片/备份;
  • 创建映射 Post http://localhost:9200/xc_course/doc/_mapping

映射的 JSON数据

 {
     "properties": {
         "description": {
             "type": "text",
             "analyzer": "ik_max_word",
             "search_analyzer": "ik_smart"
         },
         "name": {
             "type": "text",
             "analyzer": "ik_max_word",
             "search_analyzer": "ik_smart"
         },
         "pic": {
             "type": "text",
             "index": false
         },
         "price": {
             "type": "float"
         },
         "studymodel": {
             "type": "keyword"
         },
         "timestamp": {
             "type": "date",
             "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
         }
     }
 }

插入数据:post/put

 http://localhost:9200/xc_course/doc/1 
 {
     "name": "Bootstrap开发",
     "description": "Bootstrap是由Twitter推出的一个前台页面开发框架,是一个非常流行的开发框架,此框架集成了 多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松 的实现一个不受浏览器限制的精美界面效果。",
     "studymodel": "201002",
     "price": 68.6,
     "timestamp": "2018-04-25 19:11:35",
     "pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
 }
 http://localhost:9200/xc_course/doc/2 
 {
     "name": "java编程基础",
     "description": "java语言是世界第一编程语言,在软件开发领域使用人数最多。",
     "studymodel": "201002",
     "price": 68.6,
     "timestamp": "2018-04-25 19:11:35",
     "pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
 }
 http://localhost:9200/xc_course/doc/3 
 {
     "name": "spring开发基础",
     "description": "spring 在java领域非常流行,java程序员都在用。",
     "studymodel": "201001",
     "price": 88.6,
     "timestamp": "2018-04-25 19:11:35",
     "pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
 }

查询所有文档

  • Get请求 http://localhost:9200/xc_course/doc/_search
  • Post请求: http://localhost:9200/xc_course/doc/_search

Post JSON数据

 //post 请求,可以加入很多的条件...实现:分页,条件,多条件...等高级查询;
 { 
     "query": { 
     "match_all": {} 
     }
 } 

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     //查询全部数据
     public void testSearchAll ()throws Exception{
         //SearchRequest用于与搜索文档、聚合、定制查询有关的任何操作,还提供了在查询结果的基于上,对于匹配的关键词进行突出显示的方法。
         SearchRequest searchRequest = new SearchRequest("xc_course"); //指定查询的索引
         searchRequest.types("doc");  //指定查询的 映射;
         //执行查询的构造对象
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //指定查询的方式;
         searchSourceBuilder.query(QueryBuilders.matchAllQuery());
         //Source源字段的过滤,指定查询的fieid,相当于: select 列1,列2... 指定查询的列;
         searchSourceBuilder.fetchSource(new String[]{"name","description"}, new String[]{});
         //完善请求数据:传入构造对象;
         searchRequest.source(searchSourceBuilder);
 ​
         // client发送请求! 获取响应数据Response
         SearchResponse searchResponse = client.search(searchRequest , RequestOptions.DEFAULT);
         //获取到hits 属性属性
         SearchHits hits = searchResponse.getHits();
         SearchHit[] searchHits = hits.getHits();
         //循环遍历数组,渠道数据!打印输出!全部数据!
         System.out.println(searchHits);
         for (SearchHit hit : searchHits) {
             System.out.println(hit.getIndex());
             System.out.println(hit.getId());
             Map<String, Object> sourceAsMap = hit.getSourceAsMap();
             String name = (String) sourceAsMap.get("name");
             String studymodel = (String) sourceAsMap.get("description");
             System.out.println(name + "\t" + studymodel + "\t" + sourceAsMap);
         }
     };
 }

主程序测试:

  • 结果只有 name description在这里插入图片描述
  • 感谢大佬总结的图文资料: 在这里插入图片描述

分页查询

  • post请求: http://localhost:9200/xc_course/doc/_search

JSON参数

 {
     "from": 0,  //起始文档的下标,从0开始.
     "size": 1,  //查询的文档数量   
     "query": {
         "match_all": {}
     },
     "_source": ["name", "studymodel"]   //指定查询fieid
 }
  • from size _source 与query同级!

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
 ​
     //分页查询数据
     public void queryPage() throws Exception {
         SearchRequest request = new SearchRequest("xc_course");
         request.types("doc");
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //设置
         int index = 1;
         int size = 2;
         searchSourceBuilder.from((index - 1) * size);   //设置起始位置
         searchSourceBuilder.size(size);                 //设置查询的个数!
         searchSourceBuilder.query(QueryBuilders.matchAllQuery());
         
         searchSourceBuilder.fetchSource(new String[]{"name", "studymodel"}, new String[]{});
         //包装完整的请求对象
         request.source(searchSourceBuilder);
         //发起请求获取响应
         SearchResponse response = client.search(request, RequestOptions.DEFAULT);
         SearchHits searchHits = response.getHits();
         //省略输出数据!
         
     }
  }

精准Term 查询 Query

  • 在搜索时,不会进行关键词拆分整体进入数据库查询 精准查询
  • post请求: http://localhost:9200/xc_course/doc/_search
 {   
     "query": {
         //term:设置精准查询;
         "term": {              
             "name": "java"  //name 精确值Java相当于: like %_% 但值必须得是,分词表的值;     
         }
     }
 }

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     //精准查询
     public void termAll() throws Exception {
         SearchRequest request = new SearchRequest("xc_course");
         request.types("doc");
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //指定查询的方式termQuery 精准查询参数
         //注意QueryBuilders.termQuery 只支持单参精确查;
         searchSourceBuilder.query(QueryBuilders.termQuery("studymodel", "201001"));
         //包装完整的请求对象
         request.source(searchSourceBuilder);
         //发起请求获取响应
         SearchResponse response = client.search(request, RequestOptions.DEFAULT);
         SearchHits searchHits = response.getHits();
         //省略输出代码...
         
     }
 }

根据id精确匹配

  • post请求: http://localhost:9200/xc_course/doc/_search
 {
     "query": {
         //ids 设置id 请求查询...
         "ids": {
             "type": "doc",  //指定映射类型
             "values": "1"   //查询id 的值,可以使用 ["1", "2", "3"] 多选条件查,类似于in [] 
         }
     }
 }

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
     /*in查询*/
     public void inSearch() throws Exception {
         SearchRequest request = new SearchRequest("xc_course");
         request.types("doc");
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //设置ids,in []条件
         String[] ids = {"2", "3"};
         //指定查询的方式
         searchSourceBuilder.query(QueryBuilders.termsQuery("_id", ids));
         //包装完整的请求对象
         request.source(searchSourceBuilder);
         //发起请求获取响应
         SearchResponse response = client.search(request, RequestOptions.DEFAULT);
         SearchHits searchHits = response.getHits();
          //省略输出代码...
         
     }
 }

分词match查询 Query + minimum_should_match占比查:

  • post请求: http://localhost:9200/xc_course/doc/_search
 {
     "query": {
         //match:分词规则
         "match": {
             //某个fieid的查询分词...
             "description": {
                 "query": "spring框架",    //搜索查询的参数,对其进行拆分,去与文档进行匹配!
                 "operator": "or",       //or:拆分的词只要有一个成立就符合条件  and:拆分词都在文档中出现则才符合条件`精确查询`
                 "minimum_should_match": "80%"
                 //,"minimum_should_match": "80%": minimum_should_match指定文档匹配分词占比%
                 //operator=or表示只要有一个词匹配上就得分, 实现三个词至少有两个词匹配如何实现:
                 //"minimum_should_match": "80%"表示: 3个词在文档的匹配占比为80%: 3*0.8=2.4 ≈2;(至少有两个词在文档中要匹配成功)
             }
         }
     }
 }
  • 页面输出,spring框架, Elasticearch将其进行拆分, Spring 框架
  • or 只要查询文档中匹配一个分词就符合条件,and 查询文档中词都要匹配才符合条件;

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     /*分词查询*/
     public void matchSearch() throws Exception {
         SearchRequest request = new SearchRequest("xc_course");
         request.types("doc");
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //指定查询的方式,不需要设置% 直接不.即可!
         searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring开发框架").operator(Operator.OR).minimumShouldMatch("80%"));
         //包装完整的请求对象
         request.source(searchSourceBuilder);
         //发起请求获取响应
         SearchResponse response = client.search(request, RequestOptions.DEFAULT);
         SearchHits searchHits = response.getHits();
         //省略....
         
     }
 }

多Fieid分词查:

  • 普通的分词查询只支持,单个Fieid 的分词查询,multiQuery支持多个Fieid的分词查询
  • 对搜索参数进行拆分, 与多个Fieid 进行分词匹配, 还可以通过 boots来划分分词Fieid的权重
  • post请求: http://localhost:9200/xc_course/doc/_search
 {
     "query": {
         //多Fieid分词查规则;
         "multi_match": {
             //搜索框....
             "query": "spring框架",
             "minimum_should_match": "50%",
             //指定的多个 Fieid, ^设置权重;
             "fields": ["name", "description^10"]    
         }
     }
 }

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     //多字段分词查询
     public void mutilMatchSearch() throws Exception {
         SearchRequest request = new SearchRequest("xc_course");
         request.types("doc");
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //指定查询的方式: 搜索数据 多个Fieid  or  80%  name列设置权重10
         searchSourceBuilder.query(QueryBuilders.multiMatchQuery("spring css", "description", "name").operator(Operator.OR).minimumShouldMatch("80%").field("name", 10));
         //包装完整的请求对象
         request.source(searchSourceBuilder);
         //发起请求获取响应
         SearchResponse response = client.search(request, RequestOptions.DEFAULT);
         SearchHits searchHits = response.getHits();
         //省略....
         
     }
 }

boolean查询,多条件查询:

  • post请求: http://localhost:9200/xc_course/doc/_search
  • must 表示必须,多个查询条件必须都满足.
  • should 表示或者,多个查询条件只要有一个满足即可
  • must_not 表示非
 {
     "query": {
         //bool:实现多条件查;
         "bool": {
             //must: bool的多条件规则,另外还有:should must_no; (数组内部可以防止多个条件的规则)
             "must": [{
                 //多列的分词查询
                 "multi_match": {
                     "query": "spring框架",
                     "minimum_should_match": "50%",
                     "fields": ["name^10", "description"]
                 }
             }, {
                 //精准查询规则
                 "term": {
                     "studymodel": "201002"
                 }
             }]
         }
     }
 }
  • 省略更多...需要深入发掘!

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     //Bool多条件查询
     public void boolSearch() throws Exception {
         SearchRequest request = new SearchRequest("xc_course");
         request.types("doc");
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //设置多字段的分词查询对象
         MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架", "description", "name").operator(Operator.OR).minimumShouldMatch("80%").field("name", 10);
         //设置精准查询对象
         TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");
         //创建多条件对象,并将规则条件传入bool中
         BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
         boolQueryBuilder.must(matchQueryBuilder);
         boolQueryBuilder.must(termQueryBuilder);
         //指定查询的方式
         searchSourceBuilder.query(boolQueryBuilder);
         //指定查询的Fieid
         searchSourceBuilder.fetchSource(new String[]{"name", "studymodel", "description"}, new String[]{});
         //包装完整的请求对象
         request.source(searchSourceBuilder);
         //发起请求获取响应
         SearchResponse response = client.search(request, RequestOptions.DEFAULT);
         SearchHits searchHits = response.getHits();
         //....
         
     }
 }

过滤器 filter + 范围查 range

  • post请求: http://localhost:9200/xc_course/doc/_search
  • 过虑查: 是针对搜索的结果进行过虑,所以首先要有一个条件查询之后的结果集 对结果集进行的二次查询判断; 因为Filter的过滤操作是在 内存中完成的 相比Elasticearch 更快
  • range 范围查 范围过虑,保留大于等于 x 并且小于等于 y 的记录。 注意: range和term一次只能对一个Field设置范围过虑 多个就创建多个, range | term
 {
     "_source": ["name", "studymodel", "description", "price"],
     "query": {
         "bool": {
             "must": [{
                 //多列的分词查询,查询后的条件给过滤,进行内存条件判断;
                 "multi_match": {
                     "query": "spring框架",
                     "minimum_should_match": "50%",
                     "fields": ["name^10", "description"]
                 }
             }],
             //过滤规则数组
             "filter": [{
                 //详细过滤: studymodel列的精确值过滤;
                 "term": {
                     "studymodel": "201001"
                 }
             }, {
                 //范围查:   price范围过滤查  77 
                 "range": {
                     "price": {
                         "gte": 60,  //大于等于
                         "lte": 100  //小于等于
                     }
                 }
             }]
         }
     }
 }

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
    
    /*过滤条件查询*/
     public void filterSearch() throws Exception {
          SearchRequest request = new SearchRequest("xc_course");
         request.types("doc");
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //多字段的分词查询
         MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架", "description", "name").operator(Operator.OR).minimumShouldMatch("80%").field("name", 10);
         //精准查询
         TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");
         //范围查询
         RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price").gte(60).lte(100);
         //创建多条件对象
         BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
         boolQueryBuilder.must(matchQueryBuilder);
         boolQueryBuilder.filter(termQueryBuilder);
         boolQueryBuilder.filter(rangeQueryBuilder);
         //指定查询的方式
         searchSourceBuilder.query(boolQueryBuilder);
         //包装完整的请求对象
         request.source(searchSourceBuilder);
 ​
         //发起请求获取响应
         SearchResponse response = client.search(request, RequestOptions.DEFAULT);
         SearchHits searchHits = response.getHits();
         System.out.println(searchHits.totalHits);
         SearchHit[] hits = searchHits.getHits();
          //...
     }
 }

排序

  • post请求: http://localhost:9200/xc_course/doc/_search
 {
     "query": {
         "match_all": {} 
     },
     //排序规则数组:内部可以指定多列进行排序; (同级!)
     "sort": [{
         "studymodel": "desc"    //升序
     }, {
         "price": "asc"          //降序
     }]
 }

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     //排序查询
     public void orderSearch() throws Exception {
         SearchRequest request = new SearchRequest("xc_course");
         request.types("doc");
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //设置排序规则
         searchSourceBuilder.sort(new FieldSortBuilder("studymodel").order(SortOrder.DESC));
         searchSourceBuilder.sort(new FieldSortBuilder("price").order(SortOrder.ASC));
         //包装完整的请求对象
         request.source(searchSourceBuilder);
         //发起请求获取响应
         SearchResponse response = client.search(request, RequestOptions.DEFAULT);
         SearchHits searchHits = response.getHits();
         //...
     }
 }

高亮显示

  • 高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。 搭配分词使用, 使分词查看的数据,突出显示
  • post请求: http://localhost:9200/xc_course/doc/_search
 {
     "query": {
         "bool": {
             "must": [{
                 "multi_match": {
                     "query": "开发框架",
                     "minimum_should_match": "50%",
                     "fields": ["name^10", "description"],
                     "type": "best_fields"
                 }
             }]
         }
     },
     //高亮显示规则,搭配分词使用:
     "highlight": {
         //设置分词数据的前缀
         "pre_tags": ["<span style=’color:red;’>"],
         //设置分词数据的后缀
         "post_tags": ["</span>"],
         //要进行高亮的 fieid列...
         "fields": {
             "name": {},
             "description": {}
         }
     }
 }

EsService.Java

 @Service
 public class EsService {
     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     //高亮查询查询
     public void highlightSearch() throws Exception {
         SearchRequest request = new SearchRequest("xc_course");
         request.types("doc");
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //多字段的分词查询
         MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架", "description", "name").operator(Operator.OR).minimumShouldMatch("80%").field("name", 10);
         //创建多条件对象
         BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
         boolQueryBuilder.must(matchQueryBuilder);
         //指定查询规则
         searchSourceBuilder.query(boolQueryBuilder);
         //配置高亮: 分词前缀,后缀,
         HighlightBuilder highlightBuilder = new HighlightBuilder();
         highlightBuilder.preTags("<span style='color;red;'>");
         highlightBuilder.postTags("</span>");
         highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
         highlightBuilder.fields().add(new HighlightBuilder.Field("description"));
         searchSourceBuilder.highlighter(highlightBuilder);
         //包装完整的请求对象
         request.source(searchSourceBuilder);
         //发起请求获取响应
         SearchResponse response = client.search(request, RequestOptions.DEFAULT);
         //....
         SearchHits searchHits = response.getHits();     //第一个hits
         SearchHit[] hits = searchHits.getHits();        //第二个hits数组,遍历;
         for (SearchHit hit : hits) {
             //获取原始数据输出....
             Map<String, Object> sourceAsMap = hit.getSourceAsMap();
             String name = (String) sourceAsMap.get("name");     //获取源数据的name
             //获取高亮对象,数据输出...
             Map<String, HighlightField> fields = hit.getHighlightFields();
             if (fields != null) {
                 HighlightField nameField = fields.get("name");  //获取name值返回,HighlightField ————>转换成Text数组
                 if(nameField==null){    //非空判断!
                     continue;           //退出本次循环;
                 }
                 Text[] nameTxt = nameField.fragments();
                 StringBuffer nameSbf = new StringBuffer();
                 for (Text text : nameTxt) {
                     nameSbf.append(text.toString());
                 }
                 name = nameSbf.toString();
                 System.out.println("------------------------------");
             }
             String studymodel = (String) sourceAsMap.get("description");
             System.out.println(name + "\t" + studymodel + "\t" + sourceAsMap);
     }
 }

测试:

在这里插入图片描述

分组:

  • 向关系型数据库一样:Elasticearch也支持分组,指定某列进行分组... 获取某一个的各个唯一值:
  • Select 分组列 From 表 order by 分组列 desc/asc;

实例代码.Java

     @Autowired
     //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
     private RestHighLevelClient client;
 ​
     //分组
     @GetMapping("/order")
     public   List<String>order() throws Exception {
         //指定:索引/映射
         SearchRequest request = new SearchRequest("wsm");
         request.types("houst");
         //创建构造对象;
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         //构建设置分组: 设置分组别名——分组列——指定获取分组结果集数量;
         searchSourceBuilder.aggregation(AggregationBuilders.terms("typeidGroup").field("typeid").size(2));
         //放入请求中去!
         request.source(searchSourceBuilder);
         //请求
         SearchResponse search = client.search(request, RequestOptions.DEFAULT);
         //获取分组数据
         Terms categoryGroup = search.getAggregations().get("typeidGroup");  //与别名对应,返回分组的数据;!
         //处理分组后的数据;
         List<String> cateList = termsAsList(categoryGroup);
         return cateList;
     }
 ​
     //遍历分组数据——获取List<String>集合
     public List<String> termsAsList(Terms terms) {
         List<String> list = new ArrayList<>();
         //遍历分组数据:
         for (int i = 0; i < terms.getBuckets().size(); i++) {
             //获取单个分组数据,存进list中;
             String str = terms.getBuckets().get(i).getKey().toString();
             list.add(str);
         }
         return list;
     }
  • 当然分组,还可以搭配其它条件进行分组。对条件判断之后返回的结果集进行 分组处理

常用场景:

在这里插入图片描述 在这里插入图片描述

  • 京东商品的,品牌/类型/spec规格:
  • 因为商品的数量/种类/规格/款式 是非常多的而且,不停更新的所以,商城商品页面的数据都是灵活多变,的数据库数据!
  • 可以通过分组,给商品进行分组,品牌进行分组...就可以获取不同商品的多个不同的品牌... 如果是箱子,根据箱子进行查询,分组品牌即可获得所有的箱子匹配进行动态的数据展示!
  • 规格:请借鉴下面代码:

分组JSON数据处理:

     //分组查询: 的数据是唯一的...
     //返回类型: 基于,Map: key唯一,set数据也是唯一的!
     public Map<String, Set> termsAdMap(Terms terms) {
 ​
         Map<String, Set> specMap = new HashMap<>();
 ​
         Set<String> specSet = new HashSet<>();
         //循环每一条分组之后的集合数据!存入set中,确保了存入的JSON是唯一的... (因为分组数据本就是唯一的,这个可以省略,但为了方便下面的循环遍历...)
         for (int i = 0; i < terms.getBuckets().size(); i++) {
             String str = terms.getBuckets().get(i).getKeyAsString();
             specSet.add(str);
         }
         //遍历set
         for (String specStr : specSet) {
             //将一个个JSON转换成Map对象,      {'颜色': '红色', '版本': '8GB+128GB'}————————>Map等于: key value
             Map<String, String> map = JSON.parseObject(specStr, Map.class);
             //遍历map
             for (Map.Entry<String, String> entry : map.entrySet()) {    //第一次循环↓↓↓
                 //获取key value
                 String key = entry.getKey();        //颜色
                 String value = entry.getValue();    //红色
 ​
                 //获取集合中是否存储规格: 颜色,没有就创建一个;
                 Set set = specMap.get(key);
                 if (set == null) {
                     set = new HashSet();
                 }
                 set.add(value);                     //将值增进行,如果红色已经存在, set 后面覆盖前面!
                 //将新的规格数据,添加至 specMap
                 specMap.put(key, set);
             }
         }
         return specMap;
     }
  • 实现:
  • 在这里插入图片描述 规格操作: