这里使用Springboot 2.7.12版本,Elasticsearch为7.15.0。
导入依赖
org.springframework.boot
spring-boot-starter-data-elasticsearch
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 search(Map map) {
if(map!=null&&map.size()>0) {
NativeSearchQueryBuilder queryBuilder = queryBuilder(map);
//分组查询
group(queryBuilder, map);
// NativeSearchQuery nativeSearchQuery = queryBuilder.build();
SearchHits skuEsSearchHits = elasticsearchRestTemplate.search(queryBuilder.build(), SkuEs.class);
AggregationsContainer> aggregations = skuEsSearchHits.getAggregations();
Aggregations aggregations1 = (Aggregations) aggregations.aggregations();
Map searchMap = new HashMap<>();
//解析分组数据
parseGroup(aggregations1, searchMap);
//遍历返回的内容进行处理
List> searchHits = skuEsSearchHits.getSearchHits();
//将高亮的内容填充到content中
List skuEsList = searchHits.stream().map(i -> {
Map> highlightFields = i.getHighlightFields();
List 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 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("").postTags(""));
return queryBuilder;
}
public void group(NativeSearchQueryBuilder queryBuilder,Map 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 resultMap){
if(aggregations!=null){
for (Aggregation aggregation : aggregations) {
ParsedStringTerms terms = (ParsedStringTerms) aggregation;
String name = terms.getName();
List collect = terms.getBuckets().stream().map(i -> i.getKeyAsString()).collect(Collectors.toList());
resultMap.put(name,collect);
}
}
}
}
接口测试:
查询如下:
{
"data": {
"categoryList": [
"软件研发"
],
"brandList": [
"华为"
],
"list": [
{
"id": "1318594982227025922",
"name": "华为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": "华为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": "华为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": "操作成功"
}