商城搜索DSL elasticsearch 相关代码
https://www.bilibili.com/video/BV1np4y1C7Yf?p=182&vd_source=d9a52d82a1f11ceeeb7021c93269e8d2
商城搜索DSL
{"query": {"bool": {"must": [{"match": {"skuTitle": "华为"}}],"filter": [{"range": { //价格区间过滤"skuPrice": [{"gte": 0,"lte": 6000}]}},{"term": { //是否有货"hasStock": true}},{"terms": { //品牌过滤,多选"brandId": [1,2,9]}},{"term": {"catalogId": 225}},{"nested": { // 属性值搜索 ,比如:机身内存:128G,64G,如果多个属性值,需要多个nested查询"path": "attrs","query": {"bool": {"must": [{"term": {"attrs.attrId": 15}},{"terms": {"attrs.attrValue": ["海思(Hisilicon)","以官网信息为准"]}}]}}}}]}},"sort": [{"skuPrice": {"order": "desc"}}],"highlight": { //关键字高亮"pre_tags": ["<span style='color:red'>"],"post_tags": ["</span>"],"fields": {"skuTitle": {}}},"aggs": {"brand_group": { //品牌聚合"terms": {"field": "brandId","size": 10},"aggs": {"brandNameGroup": { //子聚合,品牌名字"terms": {"field": "brandName"}},"brandImgGroup": { //子聚合,品牌图片"terms": {"field": "brandImg"}}}},"catalog_group": { //分类聚合"terms": {"field": "catalogId","size": 10},"aggs": { //子聚合,分类名称"catalogNameGroup": {"terms": {"field": "catalogName"}}}},"attrs_group": { //属性值聚合"nested": {"path": "attrs"},"aggs": {"attrIdGroup": { //根据属性值来分组"terms": {"field": "attrs.attrId","size": 10},"aggs": {"attrNameGroup": { //属性名比如CUP型号"terms": {"field": "attrs.attrName","size": 10}},"attrValGroup": { //属性名比如A15,骁龙888,麒麟9000"terms": {"field": "attrs.attrValue","size": 10}}}}}}},"from": 0,"size": 10
}
请求参数
@Data
public class SearchParam {/*** 页面传递过来的全文匹配关键字*/private String keyword;/*** 品牌id,可以多选*/private List<Long> brandId;/*** 三级分类id*/private Long catalog3Id;/*** 排序条件:sort=price/salecount/hotscore_desc/asc*/private String sort;/*** 是否显示有货*/private Integer hasStock;/*** 价格区间查询*/private String skuPrice;/*** 按照属性进行筛选*/private List<String> attrs;/*** 页码*/private Integer pageNum = 1;/*** 原生的所有查询条件*/private String _queryString;}
DSL转换的java代码和结果
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.xunqi.common.es.SkuEsModel;
import com.xunqi.common.utils.R;
import com.xunqi.gulimall.search.config.GulimallElasticSearchConfig;
import com.xunqi.gulimall.search.constant.EsConstant;
import com.xunqi.gulimall.search.service.MallSearchService;
import com.xunqi.gulimall.search.vo.AttrResponseVo;
import com.xunqi.gulimall.search.vo.SearchParam;
import com.xunqi.gulimall.search.vo.SearchResult;
import com.xunqi.gulimall.search.feign.ProductFeignService;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;/*** @Description:* @Created: with IntelliJ IDEA.* @author: 夏沫止水* @createTime: 2020-06-13 14:19**/@Slf4j
@Service
public class MallSearchServiceImpl implements MallSearchService {@Autowiredprivate RestHighLevelClient esRestClient;@Resourceprivate ProductFeignService productFeignService;@Overridepublic SearchResult search(SearchParam param) {//1、动态构建出查询需要的DSL语句SearchResult result = null;//1、准备检索请求SearchRequest searchRequest = buildSearchRequest(param);try {//2、执行检索请求SearchResponse response = esRestClient.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);//3、分析响应数据,封装成我们需要的格式result = buildSearchResult(response,param);} catch (IOException e) {e.printStackTrace();}return result;}/*** 构建结果数据* 模糊匹配,过滤(按照属性、分类、品牌,价格区间,库存),完成排序、分页、高亮,聚合分析功能* @param response* @return*/private SearchResult buildSearchResult(SearchResponse response,SearchParam param) {SearchResult result = new SearchResult();//1、返回的所有查询到的商品SearchHits hits = response.getHits();List<SkuEsModel> esModels = new ArrayList<>();//遍历所有商品信息if (hits.getHits() != null && hits.getHits().length > 0) {for (SearchHit hit : hits.getHits()) {String sourceAsString = hit.getSourceAsString();SkuEsModel esModel = JSON.parseObject(sourceAsString, SkuEsModel.class);//判断是否按关键字检索,若是就显示高亮,否则不显示if (!StringUtils.isEmpty(param.getKeyword())) {//拿到高亮信息显示标题HighlightField skuTitle = hit.getHighlightFields().get("skuTitle");String skuTitleValue = skuTitle.getFragments()[0].string();esModel.setSkuTitle(skuTitleValue);}esModels.add(esModel);}}result.setProduct(esModels);//2、当前商品涉及到的所有属性信息List<SearchResult.AttrVo> attrVos = new ArrayList<>();//获取属性信息的聚合ParsedNested attrsAgg = response.getAggregations().get("attr_agg");ParsedLongTerms attrIdAgg = attrsAgg.getAggregations().get("attr_id_agg");for (Terms.Bucket bucket : attrIdAgg.getBuckets()) {SearchResult.AttrVo attrVo = new SearchResult.AttrVo();//1、得到属性的idlong attrId = bucket.getKeyAsNumber().longValue();attrVo.setAttrId(attrId);//2、得到属性的名字ParsedStringTerms attrNameAgg = bucket.getAggregations().get("attr_name_agg");String attrName = attrNameAgg.getBuckets().get(0).getKeyAsString();attrVo.setAttrName(attrName);//3、得到属性的所有值ParsedStringTerms attrValueAgg = bucket.getAggregations().get("attr_value_agg");List<String> attrValues = attrValueAgg.getBuckets().stream().map(item -> item.getKeyAsString()).collect(Collectors.toList());attrVo.setAttrValue(attrValues);attrVos.add(attrVo);}result.setAttrs(attrVos);//3、当前商品涉及到的所有品牌信息List<SearchResult.BrandVo> brandVos = new ArrayList<>();//获取到品牌的聚合ParsedLongTerms brandAgg = response.getAggregations().get("brand_agg");for (Terms.Bucket bucket : brandAgg.getBuckets()) {SearchResult.BrandVo brandVo = new SearchResult.BrandVo();//1、得到品牌的idlong brandId = bucket.getKeyAsNumber().longValue();brandVo.setBrandId(brandId);//2、得到品牌的名字ParsedStringTerms brandNameAgg = bucket.getAggregations().get("brand_name_agg");String brandName = brandNameAgg.getBuckets().get(0).getKeyAsString();brandVo.setBrandName(brandName);//3、得到品牌的图片ParsedStringTerms brandImgAgg = bucket.getAggregations().get("brand_img_agg");String brandImg = brandImgAgg.getBuckets().get(0).getKeyAsString();brandVo.setBrandImg(brandImg);brandVos.add(brandVo);}result.setBrands(brandVos);//4、当前商品涉及到的所有分类信息//获取到分类的聚合List<SearchResult.CatalogVo> catalogVos = new ArrayList<>();ParsedLongTerms catalogAgg = response.getAggregations().get("catalog_agg");for (Terms.Bucket bucket : catalogAgg.getBuckets()) {SearchResult.CatalogVo catalogVo = new SearchResult.CatalogVo();//得到分类idString keyAsString = bucket.getKeyAsString();catalogVo.setCatalogId(Long.parseLong(keyAsString));//得到分类名ParsedStringTerms catalogNameAgg = bucket.getAggregations().get("catalog_name_agg");String catalogName = catalogNameAgg.getBuckets().get(0).getKeyAsString();catalogVo.setCatalogName(catalogName);catalogVos.add(catalogVo);}result.setCatalogs(catalogVos);//===============以上可以从聚合信息中获取====================////5、分页信息-页码result.setPageNum(param.getPageNum());//5、1分页信息、总记录数long total = hits.getTotalHits().value;result.setTotal(total);//5、2分页信息-总页码-计算int totalPages = (int)total % EsConstant.PRODUCT_PAGESIZE == 0 ?(int)total / EsConstant.PRODUCT_PAGESIZE : ((int)total / EsConstant.PRODUCT_PAGESIZE + 1);result.setTotalPages(totalPages);List<Integer> pageNavs = new ArrayList<>();for (int i = 1; i <= totalPages; i++) {pageNavs.add(i);}result.setPageNavs(pageNavs);//6、构建面包屑导航if (param.getAttrs() != null && param.getAttrs().size() > 0) {List<SearchResult.NavVo> collect = param.getAttrs().stream().map(attr -> {//1、分析每一个attrs传过来的参数值SearchResult.NavVo navVo = new SearchResult.NavVo();String[] s = attr.split("_");navVo.setNavValue(s[1]);R r = productFeignService.attrInfo(Long.parseLong(s[0]));if (r.getCode() == 0) {AttrResponseVo data = r.getData("attr", new TypeReference<AttrResponseVo>() {});navVo.setNavName(data.getAttrName());} else {navVo.setNavName(s[0]);}//2、取消了这个面包屑以后,我们要跳转到哪个地方,将请求的地址url里面的当前置空//拿到所有的查询条件,去掉当前String encode = null;try {encode = URLEncoder.encode(attr,"UTF-8");encode.replace("+","%20"); //浏览器对空格的编码和Java不一样,差异化处理} catch (UnsupportedEncodingException e) {e.printStackTrace();}String replace = param.get_queryString().replace("&attrs=" + attr, "");navVo.setLink("http://search.gulimall.com/list.html?" + replace);return navVo;}).collect(Collectors.toList());result.setNavs(collect);}return result;}/*** 准备检索请求* 模糊匹配,过滤(按照属性,分类,品牌,价格区间,库存),排序,分页,高亮,聚合分析* @return*/private SearchRequest buildSearchRequest(SearchParam param) {SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();/*** 模糊匹配,过滤(按照属性,分类,品牌,价格区间,库存)*///1. 构建bool-queryBoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();//1.1 bool-mustif(!StringUtils.isEmpty(param.getKeyword())){boolQueryBuilder.must(QueryBuilders.matchQuery("skuTitle",param.getKeyword()));}//1.2 bool-fiter//1.2.1 catelogIdif(null != param.getCatalog3Id()){boolQueryBuilder.filter(QueryBuilders.termQuery("catalogId",param.getCatalog3Id()));}//1.2.2 brandIdif(null != param.getBrandId() && param.getBrandId().size() >0){boolQueryBuilder.filter(QueryBuilders.termsQuery("brandId",param.getBrandId()));}//1.2.3 attrsif(param.getAttrs() != null && param.getAttrs().size() > 0){param.getAttrs().forEach(item -> {//attrs=1_5寸:8寸&2_16G:8GBoolQueryBuilder boolQuery = QueryBuilders.boolQuery();//attrs=1_5寸:8寸String[] s = item.split("_");String attrId=s[0];String[] attrValues = s[1].split(":");//这个属性检索用的值boolQuery.must(QueryBuilders.termQuery("attrs.attrId",attrId));boolQuery.must(QueryBuilders.termsQuery("attrs.attrValue",attrValues));NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery("attrs",boolQuery, ScoreMode.None);boolQueryBuilder.filter(nestedQueryBuilder);});}//1.2.4 hasStockif(null != param.getHasStock()){boolQueryBuilder.filter(QueryBuilders.termQuery("hasStock",param.getHasStock() == 1));}//1.2.5 skuPriceif(!StringUtils.isEmpty(param.getSkuPrice())){//skuPrice形式为:1_500或_500或500_RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("skuPrice");String[] price = param.getSkuPrice().split("_");if(price.length==2){rangeQueryBuilder.gte(price[0]).lte(price[1]);}else if(price.length == 1){if(param.getSkuPrice().startsWith("_")){rangeQueryBuilder.lte(price[1]);}if(param.getSkuPrice().endsWith("_")){rangeQueryBuilder.gte(price[0]);}}boolQueryBuilder.filter(rangeQueryBuilder);}//封装所有的查询条件searchSourceBuilder.query(boolQueryBuilder);/*** 排序,分页,高亮*///排序//形式为sort=hotScore_asc/descif(!StringUtils.isEmpty(param.getSort())){String sort = param.getSort();String[] sortFileds = sort.split("_");SortOrder sortOrder="asc".equalsIgnoreCase(sortFileds[1])?SortOrder.ASC:SortOrder.DESC;searchSourceBuilder.sort(sortFileds[0],sortOrder);}//分页searchSourceBuilder.from((param.getPageNum()-1)*EsConstant.PRODUCT_PAGESIZE);searchSourceBuilder.size(EsConstant.PRODUCT_PAGESIZE);//高亮if(!StringUtils.isEmpty(param.getKeyword())){HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("skuTitle");highlightBuilder.preTags("<b style='color:red'>");highlightBuilder.postTags("</b>");searchSourceBuilder.highlighter(highlightBuilder);}/*** 聚合分析*///1. 按照品牌进行聚合TermsAggregationBuilder brand_agg = AggregationBuilders.terms("brand_agg");brand_agg.field("brandId").size(50);//1.1 品牌的子聚合-品牌名聚合brand_agg.subAggregation(AggregationBuilders.terms("brand_name_agg").field("brandName").size(1));//1.2 品牌的子聚合-品牌图片聚合brand_agg.subAggregation(AggregationBuilders.terms("brand_img_agg").field("brandImg").size(1));searchSourceBuilder.aggregation(brand_agg);//2. 按照分类信息进行聚合TermsAggregationBuilder catalog_agg = AggregationBuilders.terms("catalog_agg");catalog_agg.field("catalogId").size(20);catalog_agg.subAggregation(AggregationBuilders.terms("catalog_name_agg").field("catalogName").size(1));searchSourceBuilder.aggregation(catalog_agg);//2. 按照属性信息进行聚合NestedAggregationBuilder attr_agg = AggregationBuilders.nested("attr_agg", "attrs");//2.1 按照属性ID进行聚合TermsAggregationBuilder attr_id_agg = AggregationBuilders.terms("attr_id_agg").field("attrs.attrId");attr_agg.subAggregation(attr_id_agg);//2.1.1 在每个属性ID下,按照属性名进行聚合attr_id_agg.subAggregation(AggregationBuilders.terms("attr_name_agg").field("attrs.attrName").size(1));//2.1.1 在每个属性ID下,按照属性值进行聚合attr_id_agg.subAggregation(AggregationBuilders.terms("attr_value_agg").field("attrs.attrValue").size(50));searchSourceBuilder.aggregation(attr_agg);log.debug("构建的DSL语句 {}",searchSourceBuilder.toString());SearchRequest searchRequest = new SearchRequest(new String[]{EsConstant.PRODUCT_INDEX},searchSourceBuilder);return searchRequest;}
}
商城搜索DSL elasticsearch 相关代码相关推荐
- 畅购商城(五):Elasticsearch实现商品搜索
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 畅购商城(一):环境搭建 畅购商 ...
- 美团外卖搜索基于Elasticsearch的优化实践
美团外卖搜索工程团队在Elasticsearch的优化实践中,基于Location-Based Service(LBS)业务场景对Elasticsearch的查询性能进行优化.该优化基于Run-Len ...
- 全文搜索之 Elasticsearch
Full-text Search, 全文搜索, 搜索引擎, Elasticsearch, Distributed, Cloud 2014-06-23 概述 Elasticsearch (ES ...
- 重学Elasticsearch第1章 : Elasticsearch, Kibana概念、Elasticsearch相关术语
文章目录 Elastic Stack 是什么 ElasticSearch 概念 什么是RestFul 什么是全文检索 什么是Elasticsearch ES的应用场景 安装Elasticsearch ...
- ES搜索(ElasticSearch)入门理论篇
ElasticSearch理论篇 SQL查询方式 ES相关知识 聊聊Doug Cutting 什么是Lucene 什么是Nutch 演变 Lucene和ES搜索的关系 ES概述 使用者 对比 ES搜索 ...
- 【全文搜索引擎】Elasticsearch相关介绍与linux系统安装
概念 Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java语言开发的,并作为 ...
- 该系列主要整理收集在使用C#开发WinForm应用文章及相关代码来源于WinForms小组...
该系列主要整理收集在使用C#开发WinForm应用文章及相关代码, 平时看到大家主要使用C#来开发Asp.Net应用,这方面的文章也特别多,而关于WinForm的文章相对少很多,而自己对WinForm ...
- 从零开始搭二维激光SLAM --- Hector论文公式推导与相关代码解析
这篇文章将带领大家推导一下hector slam论文中的公式.之后再对这部分公式对应的代码进行讲解下. markdown打公式太费劲了,所以我用手写了.(懒) 然后csdn又限制了图片文件大小,我是照 ...
- 解决bug 起止时间相同 搜索不到相关数据
一.背景: 同事写了一个搜索功能,由于某些原因去了其他项目组,测试测出来他遗留下来的一个bug,领导把这个bug给了我让我解决. 二.目的: 解决起止时间相同, 搜索不到相关数据,并记录这个bug问题 ...
最新文章
- Python openpyxl 之 Excel 文档简单操作
- 近年ERP软件公司腾飞的缘由
- 《CCNA学习指南:Cisco网络设备互连(ICND1)(第4版)》——1.13节生产网络模拟问题1-1...
- 如何在另一个JavaScript文件中包含一个JavaScript文件?
- 宁波计算机软考培训机构,浙江宁波2019年下半年软考通过率约为25.7%
- 机器学习笔记(一)绪论
- 在 N 条水平线与 M 条竖直线构成的网格中,放 K 枚石子
- opentack-openstack组件及功能(1)
- Java泛型详解,通俗易懂
- java 蓝桥杯 Huffuman树
- java处理表单变量_jsp处理表单及JS和JAVA变量互传
- 目前介绍区块链最好的教学视频
- 【UmiJS学习】01-快速上手
- correct string value: '\xE8\xB6\x85\xE7\xBA\xA7...' for column 'product_description' at row 1
- 嵌入式系统测试教学实训平台系统情况
- 关于人工智能的几点看法
- 京东/淘宝的手机销售榜(前4名 -- 手机品牌 --手机型号*3 --手机分辨率 -- 手机操作系统 --安卓版本号)...
- Java 使用Socket 实现基于DTU的TCP服务器 + 数据解析 + 心跳检测
- 大家如何看待网络安全的重要性?
- PHP输出图像imagegif、imagejpeg与imagepng函数用法
热门文章
- 程序员的9个经验教训,只有亲身经历才会懂
- 第一章 计算机网络与因特网
- C++ 解析XML下载类
- 飞鸽传书2010最新版
- 黑客命令大全 (不断更新中)
- Spark介绍系列01_李孟_新浪博客
- 三维激光扫描和逆向软件配合在某剧院旋转楼梯铝板装饰前钢结构骨架整体精度检测的应用
- 单摆实验的探究及计算机模拟,大角度单摆运动的计算机模拟.pdf
- windows和Mac怎么查看ip地址
- 知乎热议:21 届校招应届生 Offer 薪资曝光,年薪 35 万+,严重倒挂老员工是互联网行业常态?...