Springboot整合Elasticsearch 7.X 复杂查询

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
简介: 这里使用Springboot 2.7.12版本,Elasticsearch为7.15.0。

这里使用Springboot 2.7.12版本,Elasticsearch为7.15.0。


导入依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

 

yaml文件配置:

elasticsearch:
      uris: http://localhost:9200

 

构建实体类,这里为商品的SKU属性表


@Data
@Document(indexName = "skusearch")
public class SkuEs {
    @Id
    private String id;
    @Field(type = FieldType.Text,analyzer = "ik_smart",searchAnalyzer = "ik_smart")
    private String name;
    private Integer price;
    private Integer num;
    private String image;
    private String images;
    private Date createTime;
    private Date updateTime;
    private String spuId;
    private Integer categoryId;
    //Keyword:不分词
    @Field(type= FieldType.Keyword)
    private String categoryName;
    private Integer brandId;
    @Field(type=FieldType.Keyword)
    private String brandName;
    @Field(type=FieldType.Keyword)
    private String skuAttribute;
    private Integer status;
}



构建service层进行复杂查询:指定条件查询,聚合查询,分页查询,排序查询,高亮等等


@Service
public class SkuSearchServiceImpl implements SkuSearchService {
    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Override
    public Map<String, Object> search(Map<String, Object> map) {
        if(map!=null&&map.size()>0) {
            NativeSearchQueryBuilder queryBuilder = queryBuilder(map);
            //分组查询
            group(queryBuilder, map);
//            NativeSearchQuery nativeSearchQuery = queryBuilder.build();
            SearchHits<SkuEs> skuEsSearchHits = elasticsearchRestTemplate.search(queryBuilder.build(), SkuEs.class);
            AggregationsContainer<?> aggregations = skuEsSearchHits.getAggregations();
            Aggregations aggregations1 = (Aggregations) aggregations.aggregations();
            Map<String, Object> searchMap = new HashMap<>();
            //解析分组数据
            parseGroup(aggregations1, searchMap);
            //遍历返回的内容进行处理
            List<SearchHit<SkuEs>> searchHits = skuEsSearchHits.getSearchHits();
            //将高亮的内容填充到content中
            List<SkuEs> skuEsList = searchHits.stream().map(i -> {
                Map<String, List<String>> highlightFields = i.getHighlightFields();
                List<String> name = highlightFields.get("name");
                i.getContent().setName(name==null?i.getContent().getName():name.get(0));
                return i.getContent();
            }).collect(Collectors.toList());
            //数据元素
            searchMap.put("list", skuEsList);
            //数据元素总数
            searchMap.put("totalElements", skuEsList.size());
            return searchMap;
        }
        return null;
    }
    public NativeSearchQueryBuilder queryBuilder(Map<String, Object> searchMap){
        NativeSearchQueryBuilder queryBuilder=new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
        if(searchMap!=null&&searchMap.size()>0){
            //根据产品关键词进行查询
            String keyword = searchMap.get("keyword").toString();
            if(!StringUtils.isEmpty(keyword))
                boolQueryBuilder.must(QueryBuilders.termQuery("name",keyword));
            //查询指定的品牌
            String brandName=searchMap.get("brand").toString();
            if(!StringUtils.isEmpty(brandName)){
                boolQueryBuilder.must(QueryBuilders.termQuery("brandName",brandName));
            }
            //根据价格进行查询,形式为gteprice-lteprice
            String price = searchMap.get("price").toString();
            if(!StringUtils.isEmpty(price)){
                String[] split = price.split("-");
                boolQueryBuilder.must(QueryBuilders.rangeQuery("price").gte(split[0]));
                if(split.length>1)
                    boolQueryBuilder.must(QueryBuilders.rangeQuery("price").lte(split[1]));
            }
        }
        //根据价格,对于查询出来的产品进行降序排列
        queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
        //分页查询
        queryBuilder.withPageable(PageRequest.of(Integer.parseInt(searchMap.get("current").toString()),Integer.parseInt(searchMap.get("size").toString())));
        queryBuilder.withQuery(boolQueryBuilder);
        //高亮设置
        queryBuilder.withHighlightFields(new HighlightBuilder.Field("name"));
        queryBuilder.withHighlightBuilder(new HighlightBuilder().preTags("<em>").postTags("</em>"));
        return queryBuilder;
    }
    public void group(NativeSearchQueryBuilder queryBuilder,Map<String, Object> searchMap){
        //用户如果没有输入分类条件,则需要将分类搜索出来,作为条件提供给用户
        if(StringUtils.isEmpty(searchMap.get("category"))){
            queryBuilder.withAggregations(AggregationBuilders.terms("categoryList").
                    field("categoryName").size(100));
        }
        //用户如果没有输入品牌条件,则需要将品牌搜索出来,作为条件提供给用户
        if(StringUtils.isEmpty(searchMap.get("brand"))){
            queryBuilder.withAggregations(AggregationBuilders.terms("brandList")
                    .field("brandName").size(100));
        }
    }
    //解析分组数据
    public void parseGroup(Aggregations aggregations, Map<String,Object> resultMap){
        if(aggregations!=null){
            for (Aggregation aggregation : aggregations) {
                ParsedStringTerms terms = (ParsedStringTerms) aggregation;
                String name = terms.getName();
                List<String> collect = terms.getBuckets().stream().map(i -> i.getKeyAsString()).collect(Collectors.toList());
                resultMap.put(name,collect);
            }
        }
    }
}



接口测试:



查询如下:


{
  "data": {
  "categoryList": [
    "软件研发"
  ],
  "brandList": [
    "华为"
  ],
  "list": [
    {
    "id": "1318594982227025922",
    "name": "<em>华为</em>Mate40 Pro 32G",
    "price": 114,
    "num": 1228,
    "image": "https://sklll.oss-cn-beijing.aliyuncs.com/secby/af1faf56-b10a-4700-9896-3143a2d1c40f.jpg",
    "images": "https://sklll.oss-cn-beijing.aliyuncs.com/secby/a65bfbe4-21b7-42b2-b5cf-47a9730e0a16.jpg,https://sklll.oss-cn-beijing.aliyuncs.com/secby/fa52ef66-7724-4d6e-bece-15eba0f8f903.jpg,https://sklll.oss-cn-beijing.aliyuncs.com/secby/734f0f17-ac73-45d3-a6bf-83e1569ce887.jpg",
    "createTime": "2020-10-20T08:48:37.000+00:00",
    "updateTime": "2023-12-30T07:41:20.000+00:00",
    "spuId": "1318594982147334146",
    "categoryId": 11159,
    "categoryName": "软件研发",
    "brandId": 11,
    "brandName": "华为",
    "skuAttribute": "{\"就业薪资\":\"10K起\",\"学习费用\":\"2万\"}",
    "status": 1,
    "attrMap": null
    },
    {
    "id": "1318596430360813570",
    "name": "<em>华为</em>Mate40 Pro 32G 1800万像素",
    "price": 112,
    "num": 1227,
    "image": "https://sklll.oss-cn-beijing.aliyuncs.com/secby/9247d041-e940-426c-8e50-06084b631063.jpg",
    "images": "https://sklll.oss-cn-beijing.aliyuncs.com/secby/5f5b7435-6cf2-4797-8f65-d4abff181390.jpg",
    "createTime": "2020-10-20T08:54:22.000+00:00",
    "updateTime": "2023-12-30T07:41:21.000+00:00",
    "spuId": "1318596430293704706",
    "categoryId": 11159,
    "categoryName": "软件研发",
    "brandId": 11,
    "brandName": "华为",
    "skuAttribute": "{\"就业薪资\":\"10K起\",\"学习费用\":\"2万\"}",
    "status": 1,
    "attrMap": null
    },
    {
    "id": "1318596430398562305",
    "name": "<em>华为</em>Mate40 Pro 128G",
    "price": 111,
    "num": 1226,
    "image": "https://sklll.oss-cn-beijing.aliyuncs.com/secby/900a3618-9884-4778-bad9-c6c31eaf3eab.jpg",
    "images": "https://sklll.oss-cn-beijing.aliyuncs.com/secby/5f5b7435-6cf2-4797-8f65-d4abff181390.jpg",
    "createTime": "2020-10-20T08:54:22.000+00:00",
    "updateTime": "2023-12-30T07:41:24.000+00:00",
    "spuId": "1318596430293704706",
    "categoryId": 11159,
    "categoryName": "软件研发",
    "brandId": 11,
    "brandName": "华为",
    "skuAttribute": "{\"就业薪资\":\"10K起\",\"学习费用\":\"2万\"}",
    "status": 1,
    "attrMap": null
    }
  ],
  "totalElements": 3
  },
  "code": 20000,
  "message": "操作成功"
}


相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
1月前
|
存储 搜索推荐 Java
|
2月前
|
Java
【极问系列】springBoot集成elasticsearch出现Unable to parse response body for Response
【极问系列】springBoot集成elasticsearch出现Unable to parse response body for Response
|
29天前
|
Java 测试技术 Maven
SpringBoot集成Elasticsearch
SpringBoot集成Elasticsearch
24 0
|
1月前
|
消息中间件 Java 关系型数据库
【二十】springboot整合ElasticSearch实战(万字篇)
【二十】springboot整合ElasticSearch实战(万字篇)
214 47
|
2月前
|
缓存 算法 索引
【Elasticsearch专栏 07】深入探索:Elasticsearch的倒排索引如何进行模糊查询和通配符查询
Elasticsearch的倒排索引支持模糊查询和通配符查询,通过特定的算法和数据结构,能够实现对关键词的模糊匹配和通配符匹配。这两种查询类型提供了更灵活的搜索功能,但可能影响查询性能,需结合优化策略使用。
|
2月前
|
Java Windows
【极光系列】springBoot集成elasticsearch
【极光系列】springBoot集成elasticsearch
|
11月前
|
NoSQL Java 测试技术
SpringBoot集成ElasticSearch在启动时报availableProcessors is already set to [8], rejecting [8]
SpringBoot集成ElasticSearch在启动时报availableProcessors is already set to [8], rejecting [8]
115 0
|
Java
ElasticSearch7入门(六)SpringBoot2.3.0集成ElasticSearch7.5.2-SpringData
ElasticSearch7入门(六)SpringBoot2.3.0集成ElasticSearch7.5.2-SpringData
293 0
|
缓存 自然语言处理 Java
springboot 2.0集成elasticsearch 7.6.2 (集群)关键字高亮显示(下)
springboot 2.0集成elasticsearch 7.6.2 (集群)关键字高亮显示(下)
181 0
|
SQL 自然语言处理 Java
springboot 2.0集成elasticsearch 7.6.2 (集群)关键字高亮显示(上)
springboot 2.0集成elasticsearch 7.6.2 (集群)关键字高亮显示
169 0
springboot 2.0集成elasticsearch 7.6.2 (集群)关键字高亮显示(上)