ElasticSearch实现商品检索
商品检索
检索入口
复杂条件检索
检索业务需要考虑的问题
商品基本的数据模型
product:{
商品的基本信息,(需要检索的名字,关键字,分类等)
商品的属性信息,(属性名+属性值+是否可以筛选,这些属性需要在平台进行筛选)
}
需要分词检索的字段 | 商品的名称(SKU销售属性参与),(副标题,关键字(加分项)) |
---|---|
需要过滤的字段 | 分类id,属性k&v组合 不分词 |
需要显示的字段 | 商品标题(高亮),商品 |
需要聚合的字段 | 品牌,分类,属性和值 |
需要排序的字段 | 综合、销量、属性和值 |
满足查询提交"小米"的所有商品的分布
他们都涉及哪些品牌,涉及哪些分类,涉及哪些商品的可筛选属性参数,涉及哪些.....
这些都是动态的,每一步不一样的都需要重新计算
商品的ES对象模型
EsProduct
@Data
public class EsProduct implements Serializable {
private static final long serialVersionUID = -1L;
private Long id; //spuId
private String productSn; //spuId-skuId
private Long brandId;
private String brandName;
private Long productCategoryId;
private String productCategoryName;
private String pic;
private String name;//这是需要检索的字段 分词
private String subTitle;//也可以检索,这是一个加分字段
private String keywords;// 也可以检索,这是一个加分字段
private BigDecimal price;//sku-price;
private Integer sale;//sku-sale
private Integer newStatus;//
private Integer recommandStatus;//
private Integer stock;//sku-stock
private Integer promotionType;//促销类型
private Integer sort;//排序
private Integer commentCount;//评论数量共享spu
private List<EsProductAttributeValue> attrValueList;//商品的筛选属性(SPU的属性;
网络制式:3G 4G 5G,
操作系统:Android IO)
EsProductAttributeValue
@Data
public class EsProductAttributeValue implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Long productAttributeId;
//属性值
private String value;//3G
//属性参数:0->规格;1->参数
private Integer type;//规格,销售属性;参数,筛选参数
//属性名称
private String name;//网络制式
}
/**
* 搜索相关商品品牌名称,分类名称及属性
*/
@Data
public class EsProductRelatedInfo {
private List<String> brandNames;
private List<String> productCategoryNames;
private List<ProductAttr> productAttrs;
@Data
public static class ProductAttr{
private Long attrId;
private String attrName;
private List<String> attrValues;
}
}
PUT /product
{
"mappings": {
"info": {
"properties": {
"attrValueList": {
"type":"nested",
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "keyword"
},
"productAttributeId": {
"type": "long"
},
"productId": {
"type": "long"
},
"type": {
"type": "long"
},
"value": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"brandId": {
"type": "long"
},
"brandName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"id": {
"type": "long"
},
"keywords": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"newStatus": {
"type": "long"
},
"pic": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"price": {
"type": "float"
},
"productCategoryId": {
"type": "long"
},
"productCategoryName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"productSn": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"promotionType": {
"type": "long"
},
"recommandStatus": {
"type": "long"
},
"sale": {
"type": "long"
},
"skuProductInfos": {
"type":"nested",
"properties": {
"attributeValues": {
"type":"nested",
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"productAttributeId": {
"type": "long"
},
"productId": {
"type": "long"
},
"type": {
"type": "long"
},
"value": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"id": {
"type": "long"
},
"lockStock": {
"type": "long"
},
"lowStock": {
"type": "long"
},
"pic": {
"type": "keyword"
},
"price": {
"type": "float"
},
"productId": {
"type": "long"
},
"skuCode": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"skuTitle": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
},
"analyzer": "ik_max_word"
},
"sp1": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"sp2": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"stock": {
"type": "long"
}
}
},
"sort": {
"type": "long"
},
"stock": {
"type": "long"
},
"subTitle": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
},
"analyzer": "ik_max_word"
}
}
}
}
}
复杂检索DSL需要考虑的问题
GET product/_search
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "skuProductInfos",
"query": {
"match": {
"skuProductInfos.skuTitle": "手机"
}
}
}
}
],
"filter": [
{
"nested": {
"path": "attrValueList",
"query": {
"bool": {
"must": [
{
"match": {
"attrValueList.name": "屏幕尺寸"
}
},
{
"match": {
"attrValueList.value.keyword": "4.7"
}
}
]
}
}
}
},
{
"nested": {
"path": "attrValueList",
"query": {
"bool": {
"must": [
{
"match": {
"attrValueList.name": "网络"
}
},
{
"match": {
"attrValueList.value.keyword": "4G"
}
}
]
}
}
}
},
{
"term": {
"brandName.keyword": "苹果"
}
},
{
"term": {
"productCategoryId": "19"
}
},
{
"range": {
"price": {
"gte": 5000,
"lte": 10000
}
}
}
]
}
},
"aggs": {
"brand_agg": {
"terms": {
"field": "brandName.keyword"
},
"aggs": {
"brandId": {
"terms": {
"field": "brandId",
"size": 10
}
}
}
},
"category_agg": {
"terms": {
"field": "productCategoryName.keyword",
"size": 10
}
},
"attr_agg": {
"nested": {
"path": "attrValueList"
},
"aggs": {
"attrName_agg": {
"terms": {
"field": "attrValueList.name",
"size": 10
},
"aggs": {
"attrValue_agg": {
"terms": {
"field": "attrValueList.value.keyword",
"size": 10
}
}
}
}
}
}
},
"highlight": {
"pre_tags": "<b style='color:red'>",
"post_tags": "</b>",
"fields": {
"skuProductInfos.skuTitle": {}
}
},
"from": 0,
"size": 12,
"sort": [
{
"price": {
"order": "asc"
}
},
{
"sort":{
"order": "asc"
}
}
]
}
复杂检索参考代码
public void testSearch(){
queryDsl(1L,3L,"小米",1);
}
public void queryDsl(Long brandId,Long productCategoryId,String keyword,int sort){
SearchSourceBuilder builder = new SearchSourceBuilder();
//1、分页
builder.from(0).size(10);
//2、搜索
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.matchQuery("name",keyword))
.should(QueryBuilders.matchQuery("subTitle",keyword))
.should(QueryBuilders.matchQuery("keywords",keyword));
if (StringUtils.isEmpty(keyword)) {
builder.query(QueryBuilders.matchAllQuery());
} else {
builder.query(boolQuery);
}
//3、过滤
if (brandId != null || productCategoryId != null) {
if (brandId != null) {
boolQuery.filter(QueryBuilders.termQuery("brandId",brandId));
}
if (productCategoryId != null) {
boolQuery.filter(QueryBuilders.termQuery("productCategoryId",productCategoryId));
}
builder.query(boolQuery);
}
//排序
if(sort==1){
//按新品从新到旧
builder.sort(SortBuilders.fieldSort("id").order(SortOrder.DESC));
}else if(sort==2){
//按销量从高到低
builder.sort(SortBuilders.fieldSort("sale").order(SortOrder.DESC));
}else if(sort==3){
//按价格从低到高
builder.sort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
}else if(sort==4){
//按价格从高到低
builder.sort(SortBuilders.fieldSort("price").order(SortOrder.ASC));
}else{
//按相关度
builder.sort(SortBuilders.scoreSort().order(SortOrder.DESC));
}
//4、聚合
//聚合所有品牌
builder.aggregation(AggregationBuilders.terms("brandNames").field("brandName"));
//聚合所有分类
builder.aggregation(AggregationBuilders.terms("productCategoryNames").field("productCategoryName"));
//聚合所有属性值
NestedAggregationBuilder nestedAggregationBuilder = AggregationBuilders.nested("allAttrValues", "attrValueList")
.subAggregation(AggregationBuilders.filter("productAttrs", QueryBuilders.termQuery("attrValueList.type", "1")))
.subAggregation(AggregationBuilders.terms("attrIds")
.field("attrValueList.productAttributeId")
.subAggregation(AggregationBuilders.terms("attrValues").field("attrValueList.value")
.subAggregation(AggregationBuilders.terms("attrNames").field("attrValueList.name"))));
builder.aggregation(nestedAggregationBuilder);
String toString = builder.toString();
System.out.println("DSL:"+toString);
}
入参封装
String keyword;
String catalog3Id;
String[] attrValues;
int pageNo=1;
int pageSize=20;
返回结果封装
List<SkuInfo> skuInfoList;
long total;
long totalPages;
List<String> attrValueList;
ES高级
嵌套桶
为了检索嵌套对象,我们在指定mapping的时候应该变为type=nested
"attrValueList": {
"type": "nested",
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "keyword"
},
"productAttributeId": {
"type": "long"
},
"type": {
"type": "long"
},
"value": {
"type": "keyword"
}
}
},