Springboot整合Elasticsearch 7.X 复杂查询

发布时间:2024年01月01日

这里使用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": "操作成功"
}

文章来源:https://blog.csdn.net/qq_43649937/article/details/135324823
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。