Elasticearch 搜索引擎(2: Java 整合Boot

2024-08-06 15:09:56 浏览数 (2)

承接上文: Elasticearch 搜索引擎

Boot 整合 Elasticearch

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

Elasticearch依赖配置:

pom.xml

代码语言:javascript复制
    <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

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

Elasticearch的配置类:

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

EsConfig

代码语言:javascript复制
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

代码语言:javascript复制
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

代码语言:javascript复制
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

代码语言:javascript复制
@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"  
                "tt"description": {n"  
                "ttt"type": "text",n"  
                "ttt"analyzer": "ik_max_word",n"  
                "ttt"search_analyzer": "ik_smart"n"  
                "tt},n"  
                "tt"name": {n"  
                "ttt"type": "text",n"  
                "ttt"analyzer": "ik_max_word",n"  
                "ttt"search_analyzer": "ik_smart"n"  
                "tt},n"  
                "tt"pic": {n"  
                "ttt"type": "text",n"  
                "ttt"index": falsen"  
                "tt},n"  
                "tt"price": {n"  
                "ttt"type": "float"n"  
                "tt},n"  
                "tt"studymodel": {n"  
                "ttt"type": "keyword"n"  
                "tt},n"  
                "tt"timestamp": {n"  
                "ttt"type": "date",n"  
                "ttt"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"n"  
                "tt}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

代码语言:javascript复制
@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

代码语言:javascript复制
@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
代码语言:javascript复制
{
   "doc" : {
      "修改Fieid" : "修改值..."
   }
}
  • 修改成功:_version版本 1;

EsService.Java

代码语言:javascript复制
@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数据

代码语言:javascript复制
{
	"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

代码语言:javascript复制
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数据

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

EsService.Java

代码语言:javascript复制
@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参数

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

EsService.Java

代码语言:javascript复制
@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
代码语言:javascript复制
{	
	"query": {
		//term:设置精准查询;
		"term": {              
			"name": "java"  //name 精确值Java相当于: like %_% 但值必须得是,分词表的值;     
		}
	}
}

EsService.Java

代码语言:javascript复制
@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
代码语言:javascript复制
{
	"query": {
        //ids 设置id 请求查询...
		"ids": {
			"type": "doc",  //指定映射类型
			"values": "1"   //查询id 的值,可以使用 ["1", "2", "3"] 多选条件查,类似于in [] 
		}
	}
}

EsService.Java

代码语言:javascript复制
@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
代码语言:javascript复制
{
	"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

代码语言:javascript复制
@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
代码语言:javascript复制
{
	"query": {
		//多Fieid分词查规则;
		"multi_match": {
			//搜索框....
			"query": "spring框架",
			"minimum_should_match": "50%",
			//指定的多个 Fieid, ^设置权重;
			"fields": ["name", "description^10"]    
		}
	}
}

EsService.Java

代码语言:javascript复制
@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 表示非
代码语言:javascript复制
{
	"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

代码语言:javascript复制
@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
代码语言:javascript复制
{
	"_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

代码语言:javascript复制
@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
代码语言:javascript复制
{
	"query": {
		"match_all": {} 
	},
    //排序规则数组:内部可以指定多列进行排序; (同级!)
	"sort": [{
		"studymodel": "desc"    //升序
	}, {
		"price": "asc"          //降序
	}]
}

EsService.Java

代码语言:javascript复制
@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
代码语言:javascript复制
{
	"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

代码语言:javascript复制
@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

代码语言:javascript复制
    @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数据处理:

代码语言:javascript复制
    //分组查询: 的数据是唯一的...
    //返回类型: 基于,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;
    }
  • 实现:

0 人点赞