一、电商项目搜索实战(上)
图灵商城搜索效果实现:
es存的字段不需要和mysql一模一样,主要看要搜索哪些字段。
根据关键字查询、根据品牌查询、商品类别、商品属性信息、价格区间、是否有库存、排序(销量、价格、
上架时间等)
ES索引库表结构分析
一个商品有很多属性,每个属性,每个属性有很多属性值。
商品有很多属性,一个属性有很多属性值
“type”: “nested”,
嵌套
ES里面存的数据不需要和MySQL一模一样
** 创建索引库**
PUT product_db
{
"mappings": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "text",
"analyzer": "ik_max_word"
},
"keywords": {
"type": "text",
"analyzer": "ik_max_word"
},
"subTitle": {
"type": "text",
"analyzer": "ik_max_word"
},
"salecount":{
"type": "long"
},
"putawayDate":{
"type": "date"
},
"price": {
"type": "double"
},
"promotionPrice": {
"type": "keyword"
},
"originalPrice": {
"type": "keyword"
},
"pic": {
"type": "keyword"
},
"sale": {
"type": "long"
},
"hasStock": {
"type": "boolean"
},
"brandId": {
"type": "long"
},
"brandName": {
"type": "keyword"
},
"brandImg": {
"type": "keyword"
},
"categoryId": {
"type": "long"
},
"categoryName": {
"type": "keyword"
},
"attrs": {
"type": "nested",
"properties": {
"attrId": {
"type": "long"
},
"attrName": {
"type": "keyword"
},
"attrValue": {
"type": "keyword"
}
}
}
}
}
}
索引数据准备
PUT /product_db/_doc/1
{
"id": "26",
"name": "小米 11 手机",
"keywords": "小米手机",
"subTitle": "AI智慧全面屏 6GB +64GB 亮黑色 全网通版 移动联通电信4G手机 双卡双待 双卡双待",
"price": "3999",
"promotionPrice": "2999",
"originalPrice": "5999",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/xiaomi.jpg",
"sale": 999,
"hasStock": true,
"salecount":999,
"putawayDate":"2021-04-01",
"brandId": 6,
"brandName": "小米",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/1e34aef2a409119018a4c6258e39ecfb_222_222.png",
"categoryId": 19,
"categoryName": "手机通讯",
"attrs": [
{
"attrId": 1,
"attrName": "cpu",
"attrValue": "2核"
},
{
"attrId": 2,
"attrName": "颜色",
"attrValue": "黑色"
}
]
}
nested嵌套查询,查什么cpu 2核
PUT /product_db/_doc/2
{
"id": "27",
"name": "小米 10 手机",
"keywords": "小米手机",
"subTitle": "AI智慧全面屏 4GB +64GB 亮白色 全网通版 移动联通电信4G手机 双卡双待 双卡双待",
"price": "2999",
"promotionPrice": "1999",
"originalPrice": "3999",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/xiaomi.jpg",
"sale": 999,
"hasStock": false,
"salecount":99,
"putawayDate":"2021-04-02",
"brandId": 6,
"brandName": "小米",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/1e34aef2a409119018a4c6258e39ecfb_222_222.png",
"categoryId": 19,
"categoryName": "手机通讯",
"attrs": [
{
"attrId": 1,
"attrName": "cpu",
"attrValue": "4核"
},
{
"attrId": 2,
"attrName": "颜色",
"attrValue": "白色"
}
]
}
PUT /product_db/_doc/3
{
"id": "28",
"name": "小米 手机",
"keywords": "小米手机",
"subTitle": "AI智慧全面屏 4GB +64GB 亮蓝色 全网通版 移动联通电信4G手机 双卡双待 双卡双待",
"price": "2999",
"promotionPrice": "1999",
"originalPrice": "3999",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/xiaomi.jpg",
"sale": 999,
"hasStock": true,
"salecount":199,
"putawayDate":"2021-04-03",
"brandId": 6,
"brandName": "小米",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/1e34aef2a409119018a4c6258e39ecfb_222_222.png",
"categoryId": 19,
"categoryName": "手机通讯",
"attrs": [
{
"attrId": 1,
"attrName": "cpu",
"attrValue": "2核"
},
{
"attrId": 2,
"attrName": "颜色",
"attrValue": "蓝色"
}
]
}
PUT /product_db/_doc/4
{
"id": "29",
"name": "Apple iPhone 8 Plus 64GB 金色特别版 移动联通电信4G手机",
"keywords": "苹果手机",
"subTitle": "苹果手机 Apple产品年中狂欢节,好物尽享,美在智慧!速来 >> 勾选[保障服务][原厂保2年],获得AppleCare+全方位服务计划,原厂延保售后无忧。",
"price": "5999",
"promotionPrice": "4999",
"originalPrice": "7999",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5acc5248N6a5f81cd.jpg",
"sale": 999,
"hasStock": true,
"salecount":1199,
"putawayDate":"2021-04-04",
"brandId": 51,
"brandName": "苹果",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180607/timg.jpg",
"categoryId": 19,
"categoryName": "手机通讯",
"attrs": [
{
"attrId": 1,
"attrName": "cpu",
"attrValue": "4核"
},
{
"attrId": 2,
"attrName": "颜色",
"attrValue": "金色"
}
]
}
PUT /product_db/_doc/5
{
"id": "30",
"name": "HLA海澜之家简约动物印花短袖T恤",
"keywords": "海澜之家衣服",
"subTitle": "HLA海澜之家短袖T恤",
"price": "199",
"promotionPrice": "99",
"originalPrice": "299",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5ad83a4fN6ff67ecd.jpg!cc_350x449.jpg",
"sale": 999,
"hasStock": true,
"salecount":19,
"putawayDate":"2021-04-05",
"brandId": 50,
"brandName": "海澜之家",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/99d3279f1029d32b929343b09d3c72de_222_222.jpg",
"categoryId": 8,
"categoryName": "T恤",
"attrs": [
{
"attrId": 3,
"attrName": "尺寸",
"attrValue": "M"
},
{
"attrId": 4,
"attrName": "颜色",
"attrValue": "黑色"
}
]
}
PUT /product_db/_doc/6
{
"id": "31",
"name": "HLA海澜之家蓝灰花纹圆领针织布短袖T恤",
"keywords": "海澜之家衣服",
"subTitle": "HLA海澜之家短袖T恤",
"price": "299",
"promotionPrice": "199",
"originalPrice": "299",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5ac98b64N70acd82f.jpg!cc_350x449.jpg",
"sale": 999,
"hasStock": true,
"salecount":399,
"putawayDate":"2021-04-06",
"brandId": 50,
"brandName": "海澜之家",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/99d3279f1029d32b929343b09d3c72de_222_222.jpg",
"categoryId": 8,
"categoryName": "T恤",
"attrs": [
{
"attrId": 3,
"attrName": "尺寸",
"attrValue": "X"
},
{
"attrId": 4,
"attrName": "颜色",
"attrValue": "蓝灰"
}
]
}
PUT /product_db/_doc/7
{
"id": "32",
"name": "HLA海澜之家短袖T恤男基础款",
"keywords": "海澜之家衣服",
"subTitle": "HLA海澜之家短袖T恤",
"price": "269",
"promotionPrice": "169",
"originalPrice": "399",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5a51eb88Na4797877.jpg",
"sale": 999,
"hasStock": true,
"salecount":399,
"putawayDate":"2021-04-07",
"brandId": 50,
"brandName": "海澜之家",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/99d3279f1029d32b929343b09d3c72de_222_222.jpg",
"categoryId": 8,
"categoryName": "T恤",
"attrs": [
{
"attrId": 3,
"attrName": "尺寸",
"attrValue": "L"
},
{
"attrId": 4,
"attrName": "颜色",
"attrValue": "蓝色"
}
]
}
PUT /product_db/_doc/8
{
"id": "33",
"name": "小米(MI)小米电视4A ",
"keywords": "小米电视机家用电器",
"subTitle": "小米(MI)小米电视4A 55英寸 L55M5-AZ/L55M5-AD 2GB+8GB HDR 4K超高清 人工智能网络液晶平板电视",
"price": "2269",
"promotionPrice": "2169",
"originalPrice": "2399",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5b02804dN66004d73.jpg",
"sale": 999,
"hasStock": true,
"salecount":132,
"putawayDate":"2021-04-09",
"brandId": 6,
"brandName": "小米",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/1e34aef2a409119018a4c6258e39ecfb_222_222.png",
"categoryId": 35,
"categoryName": "手机数码",
"attrs": [
{
"attrId": 5,
"attrName": "屏幕尺寸",
"attrValue": "52"
},
{
"attrId": 6,
"attrName": "机身颜色",
"attrValue": "黑色"
}
]
}
PUT /product_db/_doc/9
{
"id": "34",
"name": "小米(MI)小米电视4A 65英寸",
"keywords": "小米电视机家用电器",
"subTitle": "小米(MI)小米电视4A 65英寸 L55M5-AZ/L55M5-AD 2GB+8GB HDR 4K超高清 人工智能网络液晶平板电视",
"price": "3269",
"promotionPrice": "3169",
"originalPrice": "3399",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5b028530N51eee7d4.jpg",
"sale": 999,
"hasStock": true,
"salecount":999,
"putawayDate":"2021-04-10",
"brandId": 6,
"brandName": "小米",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/1e34aef2a409119018a4c6258e39ecfb_222_222.png",
"categoryId": 35,
"categoryName": "手机数码",
"attrs": [
{
"attrId": 5,
"attrName": "屏幕尺寸",
"attrValue": "65"
},
{
"attrId": 6,
"attrName": "机身颜色",
"attrValue": "金色"
}
]
}
PUT /product_db/_doc/10
{
"id": "35",
"name": "耐克NIKE 男子 休闲鞋 ROSHE RUN 运动鞋 511881-010黑色41码",
"keywords": "耐克运动鞋 鞋子",
"subTitle": "耐克NIKE 男子 休闲鞋 ROSHE RUN 运动鞋 511881-010黑色41码",
"price": "569",
"promotionPrice": "369",
"originalPrice": "899",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5b235bb9Nf606460b.jpg",
"sale": 999,
"hasStock": true,
"salecount":399,
"putawayDate":"2021-04-11",
"brandId": 58,
"brandName": "NIKE",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/timg (51).jpg",
"categoryId": 29,
"categoryName": "男鞋",
"attrs": [
{
"attrId": 7,
"attrName": "尺码",
"attrValue": "42"
},
{
"attrId": 8,
"attrName": "颜色",
"attrValue": "黑色"
}
]
}
PUT /product_db/_doc/11
{
"id": "36",
"name": "耐克NIKE 男子 气垫 休闲鞋 AIR MAX 90 ESSENTIAL 运动鞋 AJ1285-101白色41码",
"keywords": "耐克运动鞋 鞋子",
"subTitle": "AIR MAX 90 ESSENTIAL 运动鞋 AJ1285-101白色",
"price": "769",
"promotionPrice": "469",
"originalPrice": "999",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/5b19403eN9f0b3cb8.jpg",
"sale": 999,
"hasStock": true,
"salecount":499,
"putawayDate":"2021-04-13",
"brandId": 58,
"brandName": "NIKE",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/timg (51).jpg",
"categoryId": 29,
"categoryName": "男鞋",
"attrs": [
{
"attrId": 7,
"attrName": "尺码",
"attrValue": "44"
},
{
"attrId": 8,
"attrName": "颜色",
"attrValue": "白色"
}
]
}
PUT /product_db/_doc/12
{
"id": "37",
"name": "(华为)HUAWEI MateBook X Pro 2019款 13.9英寸3K触控全面屏 轻薄笔记本",
"keywords": "轻薄笔记本华为 笔记本电脑",
"subTitle": "轻薄华为笔记本 电脑",
"price": "4769",
"promotionPrice": "4469",
"originalPrice": "4999",
"pic": "http://tuling-mall.oss-cn-shenzhen.aliyuncs.com/tulingmall/images/20200317/800_800_1555752016264mp.png",
"sale": 999,
"hasStock": true,
"salecount":699,
"putawayDate":"2021-04-14",
"brandId": 3,
"brandName": "华为",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/17f2dd9756d9d333bee8e60ce8c03e4c_222_222.jpg",
"categoryId": 19,
"categoryName": "手机通讯",
"attrs": [
{
"attrId": 9,
"attrName": "容量",
"attrValue": "16G"
},
{
"attrId": 10,
"attrName": "网络",
"attrValue": "4G"
}
]
}
PUT /product_db/_doc/13
{
"id": "38",
"name": "华为nova6se 手机 绮境森林 全网通(8G+128G)",
"keywords": "轻薄笔记本华为 手机",
"subTitle": "华为nova6se 手机",
"price": "6769",
"promotionPrice": "6469",
"originalPrice": "6999",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180607/5ac1bf58Ndefaac16.jpg",
"sale": 999,
"hasStock": true,
"salecount":899,
"putawayDate":"2021-04-15",
"brandId": 3,
"brandName": "华为",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/17f2dd9756d9d333bee8e60ce8c03e4c_222_222.jpg",
"categoryId": 19,
"categoryName": "手机通讯",
"attrs": [
{
"attrId": 9,
"attrName": "容量",
"attrValue": "64G"
},
{
"attrId": 10,
"attrName": "网络",
"attrValue": "5G"
}
]
}
PUT /product_db/_doc/14
{
"id": "39",
"name": "iPhone7/6s/8钢化膜苹果8Plus全屏复盖抗蓝光防窥防偷看手机膜",
"keywords": "手机膜",
"subTitle": "iPhone7/6s/8钢化膜苹果8Plus全屏复盖抗蓝光防窥防偷看手机膜",
"price": "29",
"promotionPrice": "39",
"originalPrice": "49",
"pic": "http://tuling-mall.oss-cn-shenzhen.aliyuncs.com/tulingmall/images/20200311/6df99dab78bb2014.jpg",
"sale": 999,
"hasStock": true,
"salecount":799,
"putawayDate":"2021-04-16",
"brandId": 51,
"brandName": "苹果",
"brandImg": "http://tuling-mall.oss-cn-shenzhen.aliyuncs.com/tulingmall/images/20200311/2b84746650fc122d67749a876c453619.png",
"categoryId": 30,
"categoryName": "手机配件",
"attrs": [
{
"attrId": 11,
"attrName": "手机膜-材料",
"attrValue": "钢化"
},
{
"attrId": 12,
"attrName": "手机膜-颜色",
"attrValue": "白色"
}
]
}
PUT /product_db/_doc/15
{
"id": "40",
"name": "七匹狼短袖T恤男纯棉舒适春夏修身运动休闲短袖三条装 圆领3条装",
"keywords": "七匹狼服装 衣服",
"subTitle": "七匹狼短袖T恤男纯棉舒适春夏修身运动休闲短袖三条装 圆领3条装",
"price": "129",
"promotionPrice": "139",
"originalPrice": "149",
"pic": "http://tuling-mall.oss-cn-shenzhen.aliyuncs.com/tulingmall/images/20200311/19e846e727dff337.jpg",
"sale": 999,
"hasStock": true,
"salecount":199,
"putawayDate":"2021-04-20",
"brandId": 49,
"brandName": "七匹狼",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/18d8bc3eb13533fab466d702a0d3fd1f40345bcd.jpg",
"categoryId": 8,
"categoryName": "T恤",
"attrs": [
{
"attrId": 3,
"attrName": "尺寸",
"attrValue": "M"
},
{
"attrId": 4,
"attrName": "颜色",
"attrValue": "白色"
}
]
}
PUT /product_db/_doc/16
{
"id": "41",
"name": "华为P40 Pro手机",
"keywords": "华为手机",
"subTitle": "华为P40 Pro手机",
"price": "2129",
"promotionPrice": "2139",
"originalPrice": "2149",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180607/5ac1bf58Ndefaac16.jpg",
"sale": 999,
"hasStock": true,
"salecount":199,
"putawayDate":"2021-05-03",
"brandId": 3,
"brandName": "华为",
"brandImg": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20190129/17f2dd9756d9d333bee8e60ce8c03e4c_222_222.jpg",
"categoryId": 19,
"categoryName": "手机通讯",
"attrs": [
{
"attrId": 9,
"attrName": "容量",
"attrValue": "128G"
},
{
"attrId": 10,
"attrName": "网络",
"attrValue": "5G"
}
]
}
PUT /product_db/_doc/17
{
"id": "42",
"name": "朵唯智能手机 4G全网通 老人学生双卡双待手机",
"keywords": "朵唯手机",
"subTitle": "朵唯手机后置双摄,国产虎贲芯片!优化散热结构!浅薄机身!朵唯4月特惠!",
"price": "3129",
"promotionPrice": "3139",
"originalPrice": "3249",
"pic": "http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/images/20180615/xiaomi.jpg",
"sale": 999,
"hasStock": true,
"salecount":1199,
"putawayDate":"2021-06-01",
"brandId": 59,
"brandName": "朵唯",
"brandImg": "http://tuling-mall.oss-cn-shenzhen.aliyuncs.com/tulingmall/images/20200311/2b84746650fc122d67749a876c453619.png",
"categoryId": 19,
"categoryName": "手机通讯",
"attrs": [
{
"attrId": 9,
"attrName": "容量",
"attrValue": "32G"
},
{
"attrId": 10,
"attrName": "网络",
"attrValue": "4G"
}
]
}
query会对文档评分,得分高的排在前面,搜索框搜索的商品要评分。
仅显示有货,不需要评分,可以用filter,性能高。
检索DSL语句构建
POST /product_db/_doc/_search
{
"from": 0,
"size": 8,
"query": {
"bool": {
"must": [
{
"match": {
"name": {
"query": "手机"
}
}
}
],
"filter": [
{
"term": {
"hasStock": {
"value": true
}
}
},
{
"range": {
"price": {
"from": "1",
"to": "5000"
}
}
}
]
}
},"sort": [
{
"salecount": {
"order": "asc"
}
}
],
"aggregations": {
"brand_agg": {
"terms": {
"field": "brandId",
"size": 50
},
"aggregations": {
"brand_name_agg": {
"terms": {
"field": "brandName"
}
},
"brand_img_agg": {
"terms": {
"field": "brandImg"
}
}
}
},
"category_agg": {
"terms": {
"field": "categoryId",
"size": 50,
"min_doc_count": 1
},
"aggregations": {
"category_name_agg": {
"terms": {
"field": "categoryName"
}
}
}
},
"attr_agg": {
"nested": {
"path": "attrs"
},
"aggregations": {
"attr_id_agg": {
"terms": {
"field": "attrs.attrId"
},
"aggregations": {
"attr_name_agg": {
"terms": {
"field": "attrs.attrName"
}
},
"attr_value_agg": {
"terms": {
"field": "attrs.attrValue"
}
}
}
}
}
}
},
"highlight": {
"pre_tags": [
"<b style='color:red'>"
],
"post_tags": [
"</b>"
],
"fields": {
"name": {}
}
}
}
Postman测试
http://127.0.0.1:8085/searchList?price=1_5000&keyword=手机&sort=salecount_asc&hasStock=1&pageNum=1&pageSize=20&categoryId=19&attrs=2_蓝色&attrs=1_2核
java代码实现
控制层:
@ResponseBody
@RequestMapping(value = "/searchList")
public CommonResult<ESResponseResult> listPage(ESRequestParam param, HttpServletRequest request) {
//1、根据传递来的页面的查询参数,去es中检索商品
ESResponseResult searchResult = tulingMallSearchService.search(param);
return CommonResult.success(searchResult);
}
服务层:
@Override
public ESResponseResult search(ESRequestParam param) {
try {
//1、构建检索对象-封装请求相关参数信息
SearchRequest searchRequest = startBuildRequestParam(param);
//2、进行检索操作
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
//3、分析响应数据,封装成指定的格式
ESResponseResult responseResult = startBuildResponseResult(response, param);
return responseResult;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 封装请求参数信息
* 关键字查询、根据属性、分类、品牌、价格区间、是否有库存等进行过滤、分页、高亮、以及聚合统计品牌分类属性
*
*/
private SearchRequest startBuildRequestParam(ESRequestParam param) {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
/**
* 关键字查询、根据属性、分类、品牌、价格区间、是否有库存等进行过滤、分页、高亮、以及聚合统计品牌分类属性
*/
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
//1、
if (!StringUtils.isEmpty(param.getKeyword())) {
//单字段查询
//boolQueryBuilder.must(QueryBuilders.matchQuery("name", param.getKeyword()));
//多字段查询
boolQueryBuilder.must(QueryBuilders.multiMatchQuery(param.getKeyword(),"name","keywords","subTitle"));
}
//2、根据类目ID进行过滤
if (null != param.getCategoryId()) {
boolQueryBuilder.filter(QueryBuilders.termQuery("categoryId", param.getCategoryId()));
}
//3、根据品牌ID进行过滤
if (null != param.getBrandId() && param.getBrandId().size() > 0) {
boolQueryBuilder.filter(QueryBuilders.termsQuery("brandId", param.getBrandId()));
}
//4、根据属性进行相关过滤
if (param.getAttrs() != null && param.getAttrs().size() > 0) {
param.getAttrs().forEach(item -> {
//attrs=1_白色&2_4核
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//attrs=1_64G
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);
});
}
//5、是否有库存
if (null != param.getHasStock()) {
boolQueryBuilder.filter(QueryBuilders.termQuery("hasStock", param.getHasStock() == 1));
}
/* if (price.length == 2) {
//price: _5000
if (param.getPrice().startsWith("_")) {
rangeQueryBuilder.lte(price[1]);
}
else{
//price: 1_5000
rangeQueryBuilder.gte(price[0]).lte(price[1]);
}
} else if (price.length == 1) {
//price: 1_
if (param.getPrice().endsWith("_")) {
rangeQueryBuilder.gte(price[0]);
}
}*/
//6、根据价格过滤
if (!StringUtils.isEmpty(param.getPrice())) {
//价格的输入形式为:10-100(起始价格和最终价格)或-100(不指定起始价格)或10-(不限制最终价格)
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price");
String[] price = param.getPrice().split("_");
if (price.length == 2) {
rangeQueryBuilder.gte(price[0]).lte(price[1]);
} else if (price.length == 1) {
if (param.getPrice().startsWith("_")) {
rangeQueryBuilder.lte(price[1]);
}
if (param.getPrice().endsWith("_")) {
rangeQueryBuilder.gte(price[0]);
}
}
boolQueryBuilder.filter(rangeQueryBuilder);
}
//封装所有查询条件
searchSourceBuilder.query(boolQueryBuilder);
/**
* 实现排序、高亮、分页操作
*/
//排序
//页面传入的参数值形式 sort=price_asc/desc
if (!StringUtils.isEmpty(param.getSort())) {
String sort = param.getSort();
String[] sortFileds = sort.split("_");
System.out.println("sortFileds:"+sortFileds.length);
if(!StringUtils.isEmpty(sortFileds[0])){
SortOrder sortOrder = "asc".equalsIgnoreCase(sortFileds[1]) ? SortOrder.ASC : SortOrder.DESC;
searchSourceBuilder.sort(sortFileds[0], sortOrder);
}
}
//分页查询
searchSourceBuilder.from((param.getPageNum() - 1) * SearchConstant.PAGE_SIZE);
searchSourceBuilder.size(SearchConstant.PAGE_SIZE);
//高亮显示
if (!StringUtils.isEmpty(param.getKeyword())) {
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
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 category_agg = AggregationBuilders.terms("category_agg");
category_agg.field("categoryId").size(50);
category_agg.subAggregation(AggregationBuilders.terms("category_name_agg").field("categoryName").size(1));
searchSourceBuilder.aggregation(category_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);
System.out.println("构建的DSL语句 {}:"+ searchSourceBuilder.toString());
SearchRequest searchRequest = new SearchRequest(new String[]{SearchConstant.INDEX_NAME}, searchSourceBuilder);
return searchRequest;
}
/**
* 封装查询到的结果信息
* 关键字查询、根据属性、分类、品牌、价格区间、是否有库存等进行过滤、分页、高亮、以及聚合统计品牌分类属性
*/
private ESResponseResult startBuildResponseResult(SearchResponse response, ESRequestParam param) {
ESResponseResult result = new ESResponseResult();
//1、获取查询到的商品信息
SearchHits hits = response.getHits();
List<EsProduct> esModels = new ArrayList<>();
//2、遍历所有商品信息
if (hits.getHits() != null && hits.getHits().length > 0) {
for (SearchHit hit : hits.getHits()) {
String sourceAsString = hit.getSourceAsString();
EsProduct esModel = JSON.parseObject(sourceAsString, EsProduct.class);
//2.1 判断是否按关键字检索,若是就显示高亮,否则不显示
if (!StringUtils.isEmpty(param.getKeyword())) {
//2.2 拿到高亮信息显示标题
HighlightField name = hit.getHighlightFields().get("name");
//2.3 判断name中是否含有查询的关键字(因为是多字段查询,因此可能不包含指定的关键字,假设不包含则显示原始name字段的信息)
String nameValue = name!=null ? name.getFragments()[0].string() : esModel.getName();
esModel.setName(nameValue);
}
esModels.add(esModel);
}
}
result.setProducts(esModels);
//3、当前商品涉及到的所有品牌信息,小米手机和小米电脑都属于小米品牌,过滤重复品牌信息
Set<ESResponseResult.BrandVo> brandVos = new LinkedHashSet<>();
//获取到品牌的聚合
ParsedLongTerms brandAgg = response.getAggregations().get("brand_agg");
for (Terms.Bucket bucket : brandAgg.getBuckets()) {
ESResponseResult.BrandVo brandVo = new ESResponseResult.BrandVo();
//获取品牌的id
long brandId = bucket.getKeyAsNumber().longValue();
brandVo.setBrandId(brandId);
//获取品牌的名字
ParsedStringTerms brandNameAgg = bucket.getAggregations().get("brand_name_agg");
String brandName = brandNameAgg.getBuckets().get(0).getKeyAsString();
brandVo.setBrandName(brandName);
//获取品牌的LOGO
ParsedStringTerms brandImgAgg = bucket.getAggregations().get("brand_img_agg");
String brandImg = brandImgAgg.getBuckets().get(0).getKeyAsString();
brandVo.setBrandImg(brandImg);
System.out.println("brandId:"+brandId+"brandName:"+brandName+"brandImg");
brandVos.add(brandVo);
}
System.out.println("brandVos.size:"+brandVos.size());
result.setBrands(brandVos);
//4、当前商品相关的所有类目信息
//获取到分类的聚合
List<ESResponseResult.categoryVo> categoryVos = new ArrayList<>();
ParsedLongTerms categoryAgg = response.getAggregations().get("category_agg");
for (Terms.Bucket bucket : categoryAgg.getBuckets()) {
ESResponseResult.categoryVo categoryVo = new ESResponseResult.categoryVo();
//获取分类id
String keyAsString = bucket.getKeyAsString();
categoryVo.setCategoryId(Long.parseLong(keyAsString));
//获取分类名
ParsedStringTerms categoryNameAgg = bucket.getAggregations().get("category_name_agg");
String categoryName = categoryNameAgg.getBuckets().get(0).getKeyAsString();
categoryVo.setCategoryName(categoryName);
categoryVos.add(categoryVo);
}
result.setCategorys(categoryVos);
//5、获取商品相关的所有属性信息
List<ESResponseResult.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()) {
ESResponseResult.AttrVo attrVo = new ESResponseResult.AttrVo();
//获取属性ID值
long attrId = bucket.getKeyAsNumber().longValue();
attrVo.setAttrId(attrId);
//获取属性的名字
ParsedStringTerms attrNameAgg = bucket.getAggregations().get("attr_name_agg");
String attrName = attrNameAgg.getBuckets().get(0).getKeyAsString();
attrVo.setAttrName(attrName);
//获取属性的值
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);
//6、进行分页操作
result.setPageNum(param.getPageNum());
//获取总记录数
long total = hits.getTotalHits().value;
result.setTotal(total);
//计算总页码
int totalPages = (int) total % SearchConstant.PAGE_SIZE == 0 ?
(int) total / SearchConstant.PAGE_SIZE : ((int) total / SearchConstant.PAGE_SIZE + 1);
result.setTotalPages(totalPages);
List<Integer> pageNavs = new ArrayList<>();
for (int i = 1; i <= totalPages; i++) {
pageNavs.add(i);
}
result.setPageNavs(pageNavs);
return result;
}