SpringBoot 整合 ES 进行各种高级查询搜索 您所在的位置:网站首页 springboot整合es查询数据 SpringBoot 整合 ES 进行各种高级查询搜索

SpringBoot 整合 ES 进行各种高级查询搜索

2023-06-11 05:01| 来源: 网络整理| 查看: 265

数据准备

因为本文都是数据的搜索,所以我们需要在我们的es服务器里先插入一些数据以供我们后面使用

esUserService

public interface EsUserService extends ElasticsearchRepository { } @RestController public class EsController { @Autowired private ElasticsearchRestTemplate elasticsearchTemplate; @Autowired private EsUserService esUserService; @Autowired private RestHighLevelClient client; private String[] names = {"诸葛亮", "曹操", "李白", "韩信", "赵云", "小乔", "狄仁杰", "李四", "诸小明", "王五"}; private String[] infos = {"我来自中国的一个小乡村,地处湖南省", "我来自中国的一个大城市,名叫上海,人们称作魔都" , "我来自杭州,这是一个浪漫的城市"}; /** * 准备数据 * * @return */ @GetMapping("prepareDate") public Object saveUser() { //添加索引mapping索引会自动创建但mapping自只用默认的这会导致分词器不生效 所以这里我们手动导入mapping Random random = new Random(); List users = new ArrayList(); for (int i = 0; i private Class clazz; public BeanHandler(Class clazz) { this.clazz = clazz; } /** * 讲sql 查询结果 ResultSet转化为对象 * * @param rs * @return * @throws Exception */ public T handle(ResultSet rs) throws Exception { //结果集默认指向为第一个数据的前一个 if (rs.next()) { //根据传入的字节码创建传入的指定对象 T obj = clazz.newInstance(); //获取指定字节码信息 BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class); //获取所有属性描述器 PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { //获取结果集中对应字段名的值 Object o = rs.getObject(pd.getName()); //执行当前方法并传入参数 pd.getWriteMethod().invoke(obj, o); } return obj; } return null; } /** * 将map 利用反射转化为对象 * * @param map * @return * @throws Exception */ public T handle(Map map) throws Exception { //结果集默认指向为第一个数据的前一个 //根据传入的字节码创建传入的指定对象 T obj = clazz.newInstance(); BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { Object o = map.get(pd.getName()); if (Objects.nonNull(o)) { // !!!这里需要对属性类型做强制类型转化, o = getPropertyTypeObject(pd, o); // 下面的方法相当于属性的 set方法 pd.getWriteMethod().invoke(obj, o); } } return obj; } /** * 将对应的mapValue 强转为实体类对应的类型 * * @param pd * @param o * @return */ public Object getPropertyTypeObject(PropertyDescriptor pd, Object o) { //当前属性的类型 String name = pd.getPropertyType().getName(); name = name.substring(name.lastIndexOf(".") + 1); switch (name) { case "String": o = String.valueOf(o); break; case "Long": o = Long.valueOf(String.valueOf(o)); break; case "Double": o = Double.valueOf(String.valueOf(o)); break; case "Integer": o = Integer.valueOf(String.valueOf(o)); break; case "BigDecimal": o = new BigDecimal(String.valueOf(o)); break; } return o; } } 单条件精确查询 @PostMapping("singleConditionPreciseQuery") public Object singleConditionPreciseQuery(@RequestParam(value = "query") String query) throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.matchQuery("name", query)); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 List users = new ArrayList(); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } 范围查询 /** * 范围查询 * 包括from、to * * @return */ @PostMapping("rangeSearch1") public Object rangeSearch1(@RequestParam(value = "from") int from, @RequestParam(value = "to") int to) throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.rangeQuery("age").from(from).to(to)); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 解析查询结果 // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } /** * 范围查询 * 不包括from、to * * @return */ @PostMapping("rangeSearch2") public Object rangeSearch2(@RequestParam(value = "from") int from, @RequestParam(value = "to") int to) throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.rangeQuery("age").from(from, false).to(to, false)); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 解析查询结果 // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } /** * 范围查询 * lt:小于,gt:大于 * * @return */ @PostMapping("rangeSearch3") public Object rangeSearch3(@RequestParam(value = "from") int from, @RequestParam(value = "to") int to) throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.rangeQuery("age").lt(to).gt(from)); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 解析查询结果 // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; }

在这里插入图片描述

模糊查询,支持通配符 /** * 模糊查询,支持通配符 * * @return */ @PostMapping("vagueSearch") public Object vagueSearch(@RequestParam(value = "query") String query) throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.wildcardQuery("name", query)); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } /** * 不使用通配符的模糊查询,左右匹配 * * @return */ @PostMapping("vagueSearch1") public Object vagueSearch1(@RequestParam(value = "query") String query) throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.queryStringQuery(query).field("name")); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } /** * 多字段模糊查询 * * @return */ @PostMapping("vagueSearch2") public Object vagueSearch2(@RequestParam(value = "query") String query) throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.multiMatchQuery(query, "name", "info")); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } 排序 /** * 排序 * * @return */ @PostMapping("sortSearch") public Object sortSearch(@RequestParam(value = "query") String query) throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.multiMatchQuery(query, "name", "info")) .sort("age", SortOrder.ASC);//按照年龄正序 //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } 精确统计筛选文档数 /** * 精确统计筛选文档数,查询性能有所降低 * * @return */ @PostMapping("countSearch") public Object countSearch() throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .trackTotalHits(true); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 解析查询结果 return response; } 设置源字段过滤返回 /** * 设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段 * * @return */ @PostMapping("filterSearch") public Object filterSearch() throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .fetchSource(new String[]{"name", "age"}, new String[]{"id", "info"}); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; }

在这里插入图片描述

通过上图的结果我们也可以看出:

第一个参数结果集包括哪些字段第二个参数表示结果集不包括哪些字段

在这里插入图片描述

根据 id 精确匹配 /** * 根据Id精准查询 * * @return */ @PostMapping("searchByIds") public Object searchByIds(@RequestBody Map params) throws Exception { List ids = (List) params.get("ids"); // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.termsQuery("_id", ids)); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } matchAllQuery 搜索全部 /** * matchAllQuery 搜索全部 * * @return */ @PostMapping("martchAllQuery") public Object martchAllQuery() throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.matchAllQuery()); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } match 搜索匹配 /** * match 搜索匹配 * * @return */ @PostMapping("martch") public Object martch(@RequestBody Map params) throws Exception { List querys = (List) params.get("querys"); // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.matchQuery("name", querys)); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } bool组合查询 /** * match 搜索匹配 * * @return */ @PostMapping("martch") public Object martch(@RequestBody Map params) throws Exception { List querys = (List) params.get("querys"); // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.matchQuery("name", querys)); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); /** * bool组合查询 * * @return */ @PostMapping("boolSearch") public Object boolSearch(@RequestBody Map params) throws Exception { List queryNames = (List) params.get("names"); int maxAge = (int) params.get("maxAge"); int minAge = (int) params.get("minAge"); // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); boolQueryBuilder.must(QueryBuilders.termsQuery("name", queryNames)); boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(maxAge).gte(minAge)); builder.query(boolQueryBuilder); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; }

在这里插入图片描述

nested类型嵌套查询

有时候,我们需要查询一个对象内部类的值,发现通过平时的查询查询不到数据,这时DSL(Domain Specific language,即特定领域专用语言)出场了!

elasticsearch中的内部对象无法按预期工作,这里的问题是elasticsearch(lucene)使用的库没有内部对象的概念,因此内部对象被扁平化为一个简单的字段名称和值列表。

/** * nested类型嵌套查询 * * @return */ @PostMapping("nestedSearch") public Object nestedSearch() throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder(); //条件查询 BoolQueryBuilder mainBool=new BoolQueryBuilder(); mainBool.must(QueryBuilders.matchQuery("name", "赵六")); //nested类型嵌套查询 BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder(); boolQueryBuilder.must(QueryBuilders.matchQuery("user.name", "A")); boolQueryBuilder.must(QueryBuilders.matchQuery("user.info", "浦东")); NestedQueryBuilder nested = QueryBuilders.nestedQuery("user",boolQueryBuilder, ScoreMode.None); mainBool.must(nested); builder.query(mainBool); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } 多条件查询 + 排序 + 分页 /** * 多条件查询 + 排序 + 分页 * * @return */ @PostMapping("multiConditionSearch") public Object multiConditionSearch() throws Exception { // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder(); //条件搜索 BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder(); boolQueryBuilder.must(QueryBuilders.matchQuery ("name", "张").operator(Operator.AND);//需要 满足所有字段); boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(30).gte(20)); builder.query(boolQueryBuilder); //结果集合分页 builder.from(0).size(2); //排序 builder.sort("age",SortOrder.ASC); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 执行请求 List users = new ArrayList(); for (SearchHit searchHit : response.getHits().getHits()) { Map map = searchHit.getSourceAsMap(); BeanHandler beanHandler = new BeanHandler(User.class); User user = beanHandler.handle(map); users.add(user); } // 解析查询结果 return users; } 聚合查询 /** * 求和 * * @return */ @PostMapping("sumSearch") public Object sumSearch() throws Exception { Map result = new HashMap(); // 创建请求 SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.termsQuery("_id", new int[]{1, 2, 3})); //条件搜索 //结果集合分页 builder.from(0).size(2); builder.query(QueryBuilders.matchAllQuery()); //聚合查询 AggregationBuilder aggregation = AggregationBuilders.sum("sum_age").field("age"); builder.aggregation(aggregation); //搜索 SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("user"); searchRequest.types("_doc"); searchRequest.source(builder); // 执行请求 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 解析查询结果 return response; }

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

值得我们注意的是在进行聚合操作的fild上,如果我们该字段设置成key或者text,则会出现以下错误

在这里插入图片描述 原因是:

文本字段未针对需要每个文档字段数据(如聚合和排序)的操作进行优化,因此默认情况下禁用这些操作。

我们需要改用关键字字段。或者,在设置了text或者key的字段上设置fielddata=true,以便通过取消反转索引来加载字段数据。请注意,这可能会占用大量内存

参考文章并稍作修改,https://blog.csdn.net/zhiyikeji/article/details/128939901



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有