赞
踩
elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class);
该实例通过nativeSearchQueryBuilder.withQuery()方法构建了一个通过关键字查询,参数1是前端传递的值,参数2是指索引库中哪一个字段为关键字
nativeSearchQueryBuilder.withQuery(QueryBuilders.queryStringQuery(keywords).field("name"));
nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuCategory").field("categoryName"));
nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuCategory").field("categoryName"));
AggregatedPage<SkuMap> aggregatedPage = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class);
/**
* 获取分组的数据
* getAggregations() 获取的是集合可以根据多个域分组
* get("skuCategory") 获取指定域的集合数据 【手机,家用电器,手机配件】
*/
StringTerms skuCategory = aggregatedPage.getAggregations().get("skuCategory");
List<String> categoryList = new ArrayList<>();
for (StringTerms.Bucket bucket : skuCategory.getBuckets()) {
//获取其中一个分类的名称
String categoryName = bucket.getKeyAsString();
categoryList.add(categoryName);
}
@GetMapping
public Map search(@RequestParam(required = false) Map searchMap){
return skuInfoService.search(searchMap);
}
public Map search(Map<String, String> searchMap) { /** * elasticsearchTemplate; //执行索引库操作 * NativeSearchQueryBuilder 搜索条件构建对象 用于封装各类搜索条件 */ NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); if (searchMap != null && searchMap.size() > 0){ //获取关键字的值 String keywords = searchMap.get("keywords"); if (!StringUtils.isEmpty(keywords)){ //name es库中的name nativeSearchQueryBuilder.withQuery(QueryBuilders.queryStringQuery(keywords).field("name")); } } /** * 分组查询分类集合 * addAggregation 添加一个聚合操作 比如mysql中的group by count 等函数 * field 表示根据哪个域进行分组 es分类名称 categoryName * terms 取别名 */ nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuCategory").field("categoryName")); AggregatedPage<SkuMap> aggregatedPage = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class); /** * queryForPage 1.搜索条件封装 2.返回数据的封装 */ AggregatedPage<SkuMap> page = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class); /** * 获取分组的数据 * getAggregations() 获取的是集合可以根据多个域分组 * get("skuCategory") 获取指定域的集合数据 【手机,家用电器,手机配件】 */ StringTerms skuCategory = aggregatedPage.getAggregations().get("skuCategory"); List<String> categoryList = new ArrayList<>(); for (StringTerms.Bucket bucket : skuCategory.getBuckets()) { //获取其中一个分类的名称 String categoryName = bucket.getKeyAsString(); categoryList.add(categoryName); } //分页参数->总记录数 long totalElements = page.getTotalElements(); //分页参数->总页数 int totalPages = page.getTotalPages(); //获取结果集 List<SkuMap> content = page.getContent(); //封装返回map集合 Map<String, Object> resultMap = new HashMap<>(); resultMap.put("rows", content); resultMap.put("total", totalElements); resultMap.put("totalPages", totalPages); //分类集合 resultMap.put("categoryList",categoryList); return resultMap; }
/** * 数据搜索 * @param searchMap * @return */ @Override public Map search(Map<String, String> searchMap) { //搜索条件封装 NativeSearchQueryBuilder nativeSearchQueryBuilder = searchQueryBuilder(searchMap); //集合搜索 Map<String, Object> resultMap = searchList(nativeSearchQueryBuilder); //分类分组查询 List<String> categoryList = searchCateList(nativeSearchQueryBuilder); resultMap.put("categoryList",categoryList); return resultMap; } /** * 搜索条件封装 * @param searchMap * @return */ public NativeSearchQueryBuilder searchQueryBuilder(Map<String, String> searchMap) { /** * elasticsearchTemplate; //执行索引库操作 * NativeSearchQueryBuilder 搜索条件构建对象 用于封装各类搜索条件 */ NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); if (searchMap != null && searchMap.size() > 0){ //获取关键字的值 String keywords = searchMap.get("keywords"); if (!StringUtils.isEmpty(keywords)){ //name es库中的name nativeSearchQueryBuilder.withQuery(QueryBuilders.queryStringQuery(keywords).field("name")); } } return nativeSearchQueryBuilder; } /** * 集合搜索 * @param nativeSearchQueryBuilder * @return */ public Map<String, Object> searchList(NativeSearchQueryBuilder nativeSearchQueryBuilder) { /** * queryForPage 1.搜索条件封装 2.返回数据的封装 */ AggregatedPage<SkuMap> page = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class); //分页参数->总记录数 long totalElements = page.getTotalElements(); //分页参数->总页数 int totalPages = page.getTotalPages(); //获取结果集 List<SkuMap> content = page.getContent(); //封装返回map集合 Map<String, Object> resultMap = new HashMap<>(); resultMap.put("rows", content); resultMap.put("total", totalElements); resultMap.put("totalPages", totalPages); return resultMap; } /** * 分类分组数据查询 * @param nativeSearchQueryBuilder * @return */ public List<String> searchCateList(NativeSearchQueryBuilder nativeSearchQueryBuilder) { /** * 分组查询分类集合 * addAggregation 添加一个聚合操作 比如mysql中的group by count 等函数 * field 表示根据哪个域进行分组 es分类名称 categoryName * terms 取别名 */ nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuCategory").field("categoryName")); AggregatedPage<SkuMap> aggregatedPage = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class); /** * 获取分组的数据 * getAggregations() 获取的是集合可以根据多个域分组 * get("skuCategory") 获取指定域的集合数据 【手机,家用电器,手机配件】 */ StringTerms skuCategory = aggregatedPage.getAggregations().get("skuCategory"); List<String> categoryList = new ArrayList<>(); for (StringTerms.Bucket bucket : skuCategory.getBuckets()) { //获取其中一个分类的名称 String categoryName = bucket.getKeyAsString(); categoryList.add(categoryName); } return categoryList; }
public Map search(Map<String, String> searchMap) { //搜索条件封装 NativeSearchQueryBuilder nativeSearchQueryBuilder = searchQueryBuilder(searchMap); //集合搜索 并添加高亮 Map<String, Object> resultMap = searchList(nativeSearchQueryBuilder); //当用户选择了分类 将分类作为搜索条件,则不需要对分类进行分组搜索,该值只用作于显示分类搜索的条件 //分类分组查询 if (searchMap == null || StringUtils.isEmpty(searchMap.get("category"))){ List<String> categoryList = searchCateList(nativeSearchQueryBuilder); resultMap.put("categoryList", categoryList); } //当用户选择了品牌 将品牌作为搜索条件,则不需要对品牌进行分组搜索,该值只用作于显示品牌搜索的条件 //查询品牌集合 if (searchMap == null || StringUtils.isEmpty(searchMap.get("brand"))){ List<String> brandList = searchBrandList(nativeSearchQueryBuilder); resultMap.put("brandList", brandList); } //获取规格数据 Map<String, Set<String>> specList = searchSpecList(nativeSearchQueryBuilder); resultMap.put("specList", specList); return resultMap; } /** * 搜索条件封装 * @param searchMap * @return */ public NativeSearchQueryBuilder searchQueryBuilder(Map<String, String> searchMap) { /** * elasticsearchTemplate; //执行索引库操作 * NativeSearchQueryBuilder 搜索条件构建对象 用于封装各类搜索条件 * BoolQueryBuilder 组合条件 多条件过滤 must must—not should 组合方式 */ NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); if (searchMap != null && searchMap.size() > 0){ //获取关键字的值 String keywords = searchMap.get("keywords"); if (!StringUtils.isEmpty(keywords)){ //name es库中的name //nativeSearchQueryBuilder.withQuery(QueryBuilders.queryStringQuery(keywords).field("name")); boolQueryBuilder.must(QueryBuilders.queryStringQuery(keywords).field("name")); } //分类 category if (!StringUtils.isEmpty(searchMap.get("category"))){ boolQueryBuilder.must(QueryBuilders.termQuery("categoryName", searchMap.get("category"))); } //品牌 brand if (!StringUtils.isEmpty(searchMap.get("brand"))){ boolQueryBuilder.must(QueryBuilders.termQuery("brandName", searchMap.get("brand"))); } //规格 for (Map.Entry<String, String> entry : searchMap.entrySet()) { String key = entry.getKey(); //如果key是以spec_开始,则表示按规格条件查询 //spec_网络=4G //specMap.网络.keyword //索引库的列 if (key.startsWith("spec_")){ String value = entry.getValue(); //搜索的条件 boolQueryBuilder.must(QueryBuilders.termQuery("specMap." + key.substring(5) + ".keyword", value)); } } //价格 0-500元 500元以上 去掉中文和元获取0和500 String price = searchMap.get("price"); if (!StringUtils.isEmpty(price)){ //截取分割 price = price.replace("元","").replace("以上",""); String[] prices = price.split("-"); if (prices != null && prices.length > 0){ //rangeQuery 范围搜索 gt > boolQueryBuilder.must(QueryBuilders.rangeQuery("price").gt(Integer.parseInt(prices[0]))); if (prices.length == 2){ boolQueryBuilder.must(QueryBuilders.rangeQuery("price").lte(Integer.parseInt(prices[1]))); } } } /** * 排序 * sortField 要排序的域 * sortRule 要排序的规则 */ String sortField = searchMap.get("sortField"); String sortRule = searchMap.get("sortRule"); if (!StringUtils.isEmpty(sortField) && !StringUtils.isEmpty(sortRule)){ nativeSearchQueryBuilder.withSort( new FieldSortBuilder(sortField) // 要排序的域 .order(SortOrder.valueOf(sortRule))); // 要排序的规则desc或asc } } /** * 分页 * 不传分页参数默认第一页 * 不传size默认就3条 */ Integer[] page = coverterPage(searchMap); //页数 nativeSearchQueryBuilder.withPageable(PageRequest.of(page[0] -1,page[1])); //boolQueryBuilder 填冲给nativeSearchQueryBuilder nativeSearchQueryBuilder.withQuery(boolQueryBuilder); return nativeSearchQueryBuilder; } /** * 集合搜索 * @param nativeSearchQueryBuilder * @return */ public Map<String, Object> searchList(NativeSearchQueryBuilder nativeSearchQueryBuilder) { /** * queryForPage 1.搜索条件封装 2.返回数据的封装 * 不加高亮方法 * AggregatedPage<SkuMap> page = elasticsearchTemplate.queryForPage( nativeSearchQueryBuilder.build(), SkuMap.class); */ /** * 添加高亮 */ HighlightBuilder.Field field = new HighlightBuilder.Field("name"); //指定高亮域(按名称); //添加前缀、后缀、碎片长度(name的长度限制) field.preTags("<em style=\"color:red;\">");//前缀 高亮显示红色 field.postTags("</em>"); //后缀 field.fragmentSize(100);//关键词数据的长度 nativeSearchQueryBuilder.withHighlightFields(field); AggregatedPage<SkuMap> page = elasticsearchTemplate.queryForPage( nativeSearchQueryBuilder.build(), //条件封装 SkuMap.class, //要转换的类型 // SearchResultMapper); 执行结果集之后封装的对象中,自身是个借口 new SearchResultMapper() { @Override public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) { //存储所有转换后的高亮数据对象 List<T> list = new ArrayList<>(); //searchResponse.getHits() 获取所有数据 for (SearchHit hit : searchResponse.getHits()) { //获取非高亮数据并转换成对象 SkuMap skuMap = JSON.parseObject(hit.getSourceAsString(),SkuMap.class); //获取高亮数据 HighlightField name = hit.getHighlightFields().get("name"); //getFragments 碎片长度不等于空 if (name != null && name.getFragments() != null){ //读取高亮数据 Text[] fragments = name.getFragments(); StringBuffer stringBuffer = new StringBuffer(); for (Text text : fragments) { stringBuffer.append(text.toString()); } //将非高亮数据指定的域替换成高亮数据 skuMap.setName(stringBuffer.toString()); } list.add((T) skuMap); } /** * 返回AggregatedPage接口的实现类 AggregatedPageImpl * ① 返回的数据 * ② 分页对象信息 * ③ 搜索的记录条数 */ return new AggregatedPageImpl<T>(list, pageable, searchResponse.getHits().getTotalHits()); } }); //分页参数->总记录数 long totalElements = page.getTotalElements(); //分页参数->总页数 int totalPages = page.getTotalPages(); //获取结果集 List<SkuMap> content = page.getContent(); //封装返回map集合 Map<String, Object> resultMap = new HashMap<>(); resultMap.put("rows", content); resultMap.put("total", totalElements); resultMap.put("totalPages", totalPages); return resultMap; } /** * 分类分组数据查询 * @param nativeSearchQueryBuilder * @return */ public List<String> searchCateList(NativeSearchQueryBuilder nativeSearchQueryBuilder) { /** * 分组查询分类集合 * addAggregation 添加一个聚合操作 比如mysql中的group by count 等函数 * field 表示根据哪个域进行分组 es分类名称 categoryName * terms 取别名 */ nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuCategory").field("categoryName")); AggregatedPage<SkuMap> aggregatedPage = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class); /** * 获取分组的数据 * getAggregations() 获取的是集合可以根据多个域分组 * get("skuCategory") 获取指定域的集合数据 【手机,家用电器,手机配件】 */ StringTerms skuCategory = aggregatedPage.getAggregations().get("skuCategory"); List<String> categoryList = new ArrayList<>(); for (StringTerms.Bucket bucket : skuCategory.getBuckets()) { //获取其中一个分类的名称 String categoryName = bucket.getKeyAsString(); categoryList.add(categoryName); } return categoryList; } /** * 品牌分组数据查询 * @param nativeSearchQueryBuilder * @return */ public List<String> searchBrandList(NativeSearchQueryBuilder nativeSearchQueryBuilder) { /** * 品牌分组数据查询 * addAggregation 添加一个聚合操作 比如mysql中的group by count 等函数 * field 表示根据哪个域进行分组 es分类名称 categoryName * terms 取别名 */ nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuBrand").field("brandName")); AggregatedPage<SkuMap> aggregatedPage = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class); /** * 获取分组的数据 * getAggregations() 获取的是集合可以根据多个域分组 * get("skuCategory") 获取指定域的集合数据 【TCL.华为,小米】 */ StringTerms stringTerms = aggregatedPage.getAggregations().get("skuBrand"); List<String> brandList = new ArrayList<>(); for (StringTerms.Bucket bucket : stringTerms.getBuckets()) { //获取其中一个分类的名称 String brandName = bucket.getKeyAsString(); brandList.add(brandName); } return brandList; } /** * 规格分组数据查询 * @param nativeSearchQueryBuilder * @return */ public Map<String, Set<String>> searchSpecList(NativeSearchQueryBuilder nativeSearchQueryBuilder) { /** * spec.keyword keyword不分词 * size 可以不设置,默认查询数量10 */ //nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuSpec").field("spec.keyword")); nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuSpec").field("spec.keyword").size(10000)); AggregatedPage<SkuMap> aggregatedPage = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class); /** * 获取分组的数据 * getAggregations() 获取的是集合可以根据多个域分组 * get("skuSpec") 获取指定域的集合数据 [{"尺寸":"20寸","音响效果":"立体声"},{"音响效果":"小影院","尺寸":"21寸"}] */ StringTerms stringTerms = aggregatedPage.getAggregations().get("skuSpec"); List<String> specList = new ArrayList<>(); for (StringTerms.Bucket bucket : stringTerms.getBuckets()) { //获取其中一个规格的名称 String specName = bucket.getKeyAsString(); specList.add(specName); } Map<String, Set<String>> allSpec = putSpecAll(specList); return allSpec; } /** * 规格汇总合并 * @param specList * @return */ public Map<String, Set<String>> putSpecAll(List<String> specList) { //将List中的json字符转转换成map并将每个map合并成一个map<String,<Set<String>> //合并后的map对象 Map<String, Set<String>> allSpec = new HashMap<>(); for (String spec : specList) { //转map Map <String, String> specMap = JSON.parseObject(spec, Map.class); //合并到allspec中 for (Map.Entry<String, String> entry : specMap.entrySet()) { String key = entry.getKey(); //规格的名称 尺寸 String value = entry.getValue(); //规格的值 //先从allSpec中获取一次当前规格对应的set集合数据 Set<String> strings = allSpec.get(key); if (strings == null) { //如果没有改规格 strings = new HashSet<>(); } strings.add(value); allSpec.put(key,strings); } } return allSpec; } /** * 前端分页参数 * @param searchMap * @return */ public Integer[] coverterPage(Map<String, String> searchMap) { Integer[] param = new Integer[2]; if (searchMap != null) { String pageNum = searchMap.get("pageNum"); String size = searchMap.get("size"); try { param[0] = Integer.parseInt(pageNum); param[1] = Integer.parseInt(size); return param; } catch (NumberFormatException e) { } } param[0] = 1; param[1] = 3; return param; }
/** * 数据搜索 * @param searchMap * @return */ @Override public Map search(Map<String, String> searchMap) { //搜索条件封装 NativeSearchQueryBuilder nativeSearchQueryBuilder = searchQueryBuilder(searchMap); //集合搜索 并添加高亮 Map<String, Object> resultMap = searchList(nativeSearchQueryBuilder); Map<String, Object> groupList = searchGroupList(nativeSearchQueryBuilder, searchMap); resultMap.putAll(groupList); return resultMap; } /** * 封装 分类 品牌 规格 * @param nativeSearchQueryBuilder * @return */ public Map<String, Object> searchGroupList(NativeSearchQueryBuilder nativeSearchQueryBuilder,Map<String, String> searchMap) { //分类 if (searchMap == null || StringUtils.isEmpty(searchMap.get("category"))){ nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuCategory").field("categoryName")); } //品牌 if (searchMap == null || StringUtils.isEmpty(searchMap.get("brand"))){ nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuBrand").field("brandName")); } //规格 nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuSpec").field("spec.keyword").size(10000)); AggregatedPage<SkuMap> aggregatedPage = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuMap.class); //返回map 存储所有返回的数据 Map<String, Object> groupMapResult = new HashMap<>(); if (searchMap == null || StringUtils.isEmpty(searchMap.get("category"))){ StringTerms categoryTerms = aggregatedPage.getAggregations().get("skuCategory"); List<String> categoryList = groupTerms(categoryTerms); groupMapResult.put("categoryList", categoryList); } if (searchMap == null || StringUtils.isEmpty(searchMap.get("brand"))){ StringTerms brandTerms = aggregatedPage.getAggregations().get("skuBrand"); List<String> brandList = groupTerms(brandTerms); groupMapResult.put("brandList", brandList); } //规格 StringTerms skuSpecTerms = aggregatedPage.getAggregations().get("skuSpec"); List<String> SpecList = groupTerms(skuSpecTerms); Map<String, Set<String>> stringSetMap = putSpecAll(SpecList); //合并返回 groupMapResult.put("specList", stringSetMap); return groupMapResult; } /** * 返回分组结合数据 * @param stringTerms * @return */ public List<String> groupTerms(StringTerms stringTerms){ List<String> groupTermsList = new ArrayList<>(); for (StringTerms.Bucket bucket : stringTerms.getBuckets()) { String fieldName = bucket.getKeyAsString(); groupTermsList.add(fieldName); } return groupTermsList; }
http://127.0.0.1:10086/search?brand=华为?category=笔记本.....
demo连接地址
https://e.coding.net/mzjmc/elasticsearch/elasticsearch.git
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。