elasticsearch實現類似京東的商品搜索效果(elasticsearch動態聚合)

用到京東的對其搜索應該不會陌生,其搜索也是使用elasticsearch完成的,下圖爲一個搜索效果圖:

 

搜索篩選條件會根據查詢返回的結果動態變化,要實現這個功能就要用到elasticsearch的聚合功能,先看下商品索引對應的映射:

{
  "mapping": {
    "es-product": {
      "dynamic_templates": [
        {
          "strings_as_keyword": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "keyword"
            }
          }
        }
      ],
      "properties": {
        "aggProperties": {
          "type": "nested",
          "properties": {
            "key": {
              "type": "keyword"
            },
            "value": {
              "type": "keyword"
            }
          }
        },
        "brandName": {
          "type": "keyword"
        },
        "id": {
          "type": "keyword"
        },
        "level1Category": {
          "type": "keyword"
        },
        "level2Category": {
          "type": "keyword"
        },
        "level3Category": {
          "type": "keyword"
        },
        "mainTitle": {
          "type": "text",
          "analyzer": "ik_max_word"
        },
        "searchProperties": {
          "properties": {
            "光澤度": {
              "type": "keyword"
            },
            "光源個數": {
              "type": "keyword"
            },
            "光源類型": {
              "type": "keyword"
            },
            "功率": {
              "type": "keyword"
            },
            "包裝體積": {
              "type": "keyword"
            },
            "型號": {
              "type": "keyword"
            },
            "密度": {
              "type": "keyword"
            },
            "導熱性": {
              "type": "keyword"
            },
            "導電性": {
              "type": "keyword"
            },
            "延展性": {
              "type": "keyword"
            },
            "抗氧化性": {
              "type": "keyword"
            },
            "是否帶護欄": {
              "type": "keyword"
            },
            "是否帶軟靠": {
              "type": "keyword"
            },
            "是否帶遙控器": {
              "type": "keyword"
            },
            "照射面積": {
              "type": "keyword"
            },
            "熔點": {
              "type": "keyword"
            },
            "磁性": {
              "type": "keyword"
            },
            "表面機理": {
              "type": "keyword"
            },
            "適用人數": {
              "type": "keyword"
            },
            "適用空間": {
              "type": "keyword"
            },
            "風格": {
              "type": "keyword"
            }
          }
        },
        "subTitle": {
          "type": "keyword"
        }
      }
    }
  }
}

searchProperties部分爲動態屬性,使用elasticsearch的dynamic template配置,aggProperties部分爲動態聚合所用,通過aggProperties下面的值動態聚合滿足條件的搜索結果所具有的所有屬性,比如光澤度、熔點等,而searchProperties是爲搜索使用,先說下屬性動態聚合的實現,下面是elasticsearch的查詢腳本:

{
  "from" : 0, "size" : 100,
  "query": {
    "bool":{
      "must":[{
        "match" : {
          "mainTitle" : "拉手"
        }
      }
      ]
    }
  },
  "aggs": {
    "dynamicproperty": {
      "nested": {
        "path": "aggProperties"
      },
      "aggs": {
        "name": {
          "terms": {
            "field": "aggProperties.key"
          },
          "aggs": {
            "value": {
              "terms": {
                "field": "aggProperties.value"
              }
            }
          }
        }
      }
    }
  }
}

通過上面的搜索得到下面結果:

{
    "took": 13,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 8,
        "max_score": 1.3591974,
        "hits": [
            {
                "_index": "smp-product",
                "_type": "es-product",
                "_id": "2c95ae137157829c017157c3c61c0089",
                "_score": 1.3591974,
                "_source": {
                    "id": "2c95ae137157829c017157c3c61c0089",
                    "mainTitle": "富達銘黑色隱形拉手免打孔鋁合金拉手一字型暗拉手櫥櫃衣櫃門長把手隱藏拉手長拉手 咖啡150mm",
                    "subTitle": "",
                    "brandName": "三葉",
                    "aggProperties": [
                        {
                            "key": "密度",
                            "value": "2000克/cm³"
                        },
                        {
                            "key": "熔點",
                            "value": "2000℃"
                        },
                        {
                            "key": "導熱性",
                            "value": "很好"
                        },
                        {
                            "key": "延展性",
                            "value": "易鍛物質,不需退火可錘鍊可壓延"
                        },
                        {
                            "key": "導電性",
                            "value": "是"
                        },
                        {
                            "key": "磁性",
                            "value": "順磁材料"
                        },
                        {
                            "key": "光澤度",
                            "value": "啞光"
                        },
                        {
                            "key": "表面機理",
                            "value": "拉絲"
                        },
                        {
                            "key": "抗氧化性",
                            "value": "中"
                        }
                    ],
                    "searchProperties": {
                        "表面機理": "拉絲",
                        "抗氧化性": "中",
                        "導熱性": "很好",
                        "延展性": "易鍛物質,不需退火可錘鍊可壓延",
                        "磁性": "順磁材料",
                        "導電性": "是",
                        "密度": "2000克/cm³",
                        "熔點": "2000℃",
                        "光澤度": "啞光"
                    }
                }
            },
            {
                "_index": "smp-product",
                "_type": "es-product",
                "_id": "2c95ae137157829c017157ad040c004d",
                "_score": 1.2214447,
                "_source": {
                    "id": "2c95ae137157829c017157ad040c004d",
                    "mainTitle": "致諾 老式鐵皮拉手 不鏽鋼拉手大木門蟹殼拉手 明裝四孔鐵皮門輕把手簡易拉手老式通用型防盜門把手 大號2個價格",
                    "subTitle": "",
                    "brandName": "三葉",
                    "aggProperties": [
                        {
                            "key": "密度",
                            "value": "1000克/cm³"
                        },
                        {
                            "key": "熔點",
                            "value": "1000℃"
                        },
                        {
                            "key": "導熱性",
                            "value": "較好"
                        },
                        {
                            "key": "延展性",
                            "value": "易鍛物質,不需退火可錘鍊可壓延"
                        }
                    ],
                    "searchProperties": {
                        "導熱性": "較好",
                        "延展性": "易鍛物質,不需退火可錘鍊可壓延",
                        "密度": "1000克/cm³",
                        "熔點": "1000℃"
                    }
                }
            },
            {
                "_index": "smp-product",
                "_type": "es-product",
                "_id": "2c95ae137157829c017157a991b60011",
                "_score": 1.1077276,
                "_source": {
                    "id": "2c95ae137157829c017157a991b60011",
                    "mainTitle": "卡貝拉手衣櫃門拉手抽屜櫥櫃衣櫃鞋櫃高檔門把手現代簡約五金配件",
                    "subTitle": "",
                    "brandName": "宗藝石材",
                    "aggProperties": [
                        {
                            "key": "密度",
                            "value": "1000克/cm³"
                        },
                        {
                            "key": "熔點",
                            "value": "2000℃"
                        },
                        {
                            "key": "導熱性",
                            "value": "較好"
                        },
                        {
                            "key": "導電性",
                            "value": "否"
                        },
                        {
                            "key": "磁性",
                            "value": "順磁材料"
                        },
                        {
                            "key": "光澤度",
                            "value": "啞光"
                        },
                        {
                            "key": "表面機理",
                            "value": "拉絲"
                        },
                        {
                            "key": "抗氧化性",
                            "value": "中"
                        }
                    ],
                    "searchProperties": {
                        "表面機理": "拉絲",
                        "抗氧化性": "中",
                        "導熱性": "較好",
                        "磁性": "順磁材料",
                        "導電性": "否",
                        "密度": "1000克/cm³",
                        "熔點": "2000℃",
                        "光澤度": "啞光"
                    }
                }
            },
            {
                "_index": "smp-product",
                "_type": "es-product",
                "_id": "2c95ae137157829c017157c5c98100a7",
                "_score": 0.77200073,
                "_source": {
                    "id": "2c95ae137157829c017157c5c98100a7",
                    "mainTitle": "CD超代歐式簡約陶瓷衣櫃櫃門抽屜把手小拉手 田園大理石陶瓷酒櫃拉手 單隻價格 A7-96孔距-長120mm",
                    "subTitle": "",
                    "brandName": "三葉",
                    "aggProperties": [
                        {
                            "key": "密度",
                            "value": "1500克/cm³"
                        },
                        {
                            "key": "熔點",
                            "value": "1600℃"
                        },
                        {
                            "key": "導熱性",
                            "value": "較好"
                        },
                        {
                            "key": "延展性",
                            "value": "易鍛物質,不需退火可錘鍊可壓延"
                        },
                        {
                            "key": "導電性",
                            "value": "是"
                        },
                        {
                            "key": "磁性",
                            "value": "順磁材料"
                        },
                        {
                            "key": "光澤度",
                            "value": "啞光"
                        },
                        {
                            "key": "表面機理",
                            "value": "拉絲"
                        },
                        {
                            "key": "抗氧化性",
                            "value": "高"
                        }
                    ],
                    "searchProperties": {
                        "表面機理": "拉絲",
                        "抗氧化性": "高",
                        "導熱性": "較好",
                        "延展性": "易鍛物質,不需退火可錘鍊可壓延",
                        "磁性": "順磁材料",
                        "導電性": "是",
                        "密度": "1500克/cm³",
                        "熔點": "1600℃",
                        "光澤度": "啞光"
                    }
                }
            },
            {
                "_index": "smp-product",
                "_type": "es-product",
                "_id": "2c95ae137157829c017157aaa03d0022",
                "_score": 0.7351246,
                "_source": {
                    "id": "2c95ae137157829c017157aaa03d0022",
                    "mainTitle": "適用於步陽羣升新多星月神春天進戶大門防盜門把手 拉手面板雙快加厚實",
                    "subTitle": "",
                    "brandName": "西門子",
                    "aggProperties": [
                        {
                            "key": "密度",
                            "value": "1000克/cm³"
                        },
                        {
                            "key": "熔點",
                            "value": "1500℃"
                        },
                        {
                            "key": "導熱性",
                            "value": "較好"
                        },
                        {
                            "key": "延展性",
                            "value": "易鍛物質,不需退火可錘鍊可壓延"
                        }
                    ],
                    "searchProperties": {
                        "導熱性": "較好",
                        "延展性": "易鍛物質,不需退火可錘鍊可壓延",
                        "密度": "1000克/cm³",
                        "熔點": "1500℃"
                    }
                }
            },
            {
                "_index": "smp-product",
                "_type": "es-product",
                "_id": "2c95ae137157829c017157ac51f9003f",
                "_score": 0.6896249,
                "_source": {
                    "id": "2c95ae137157829c017157ac51f9003f",
                    "mainTitle": "防盜門把手拉手進戶門拉手雙活雙快執手手柄加厚大門鎖具配件 加厚鋁合金門把手 >55mm 通用型 不帶鑰匙",
                    "subTitle": "",
                    "brandName": "西門子",
                    "aggProperties": [
                        {
                            "key": "密度",
                            "value": "1500克/cm³"
                        },
                        {
                            "key": "熔點",
                            "value": "2000℃"
                        },
                        {
                            "key": "導熱性",
                            "value": "較好"
                        },
                        {
                            "key": "延展性",
                            "value": "易鍛物質,不需退火可錘鍊可壓延"
                        },
                        {
                            "key": "導電性",
                            "value": "是"
                        },
                        {
                            "key": "磁性",
                            "value": "順磁材料"
                        },
                        {
                            "key": "光澤度",
                            "value": "高光"
                        },
                        {
                            "key": "表面機理",
                            "value": "拉絲"
                        },
                        {
                            "key": "抗氧化性",
                            "value": "中"
                        }
                    ],
                    "searchProperties": {
                        "表面機理": "拉絲",
                        "抗氧化性": "中",
                        "導熱性": "較好",
                        "延展性": "易鍛物質,不需退火可錘鍊可壓延",
                        "磁性": "順磁材料",
                        "導電性": "是",
                        "密度": "1500克/cm³",
                        "熔點": "2000℃",
                        "光澤度": "高光"
                    }
                }
            },
            {
                "_index": "smp-product",
                "_type": "es-product",
                "_id": "2c95ae137157829c017157add2c8005c",
                "_score": 0.4982656,
                "_source": {
                    "id": "2c95ae137157829c017157add2c8005c",
                    "mainTitle": "匯樂斯 防盜門把手拉手執手大門把手門把手門鎖把手鎖體鎖帽 面板把手一對/配件+外固定把手 左開",
                    "subTitle": "",
                    "brandName": "三棵樹",
                    "aggProperties": [
                        {
                            "key": "密度",
                            "value": "1000克/cm³"
                        },
                        {
                            "key": "熔點",
                            "value": "1000℃"
                        },
                        {
                            "key": "導熱性",
                            "value": "很好"
                        },
                        {
                            "key": "延展性",
                            "value": "易鍛物質,不需退火可錘鍊可壓延"
                        }
                    ],
                    "searchProperties": {
                        "導熱性": "很好",
                        "延展性": "易鍛物質,不需退火可錘鍊可壓延",
                        "密度": "1000克/cm³",
                        "熔點": "1000℃"
                    }
                }
            },
            {
                "_index": "smp-product",
                "_type": "es-product",
                "_id": "2c95ae137157829c017157c4cb880098",
                "_score": 0.48578173,
                "_source": {
                    "id": "2c95ae137157829c017157c4cb880098",
                    "mainTitle": "防盜門把手拉手雙活雙快執手手柄大門鎖配件鋁合金門把手 加厚白金帶點固定款(13*13) >55mm 通用型 不帶鑰匙",
                    "subTitle": "",
                    "brandName": "三葉",
                    "aggProperties": [
                        {
                            "key": "密度",
                            "value": "1500克/cm³"
                        },
                        {
                            "key": "熔點",
                            "value": "1500℃"
                        },
                        {
                            "key": "導熱性",
                            "value": "較好"
                        },
                        {
                            "key": "延展性",
                            "value": "易鍛物質,不需退火可錘鍊可壓延"
                        },
                        {
                            "key": "導電性",
                            "value": "否"
                        },
                        {
                            "key": "磁性",
                            "value": "鐵磁材料"
                        },
                        {
                            "key": "光澤度",
                            "value": "高光"
                        },
                        {
                            "key": "表面機理",
                            "value": "拉絲"
                        },
                        {
                            "key": "抗氧化性",
                            "value": "中"
                        }
                    ],
                    "searchProperties": {
                        "表面機理": "拉絲",
                        "抗氧化性": "中",
                        "導熱性": "較好",
                        "延展性": "易鍛物質,不需退火可錘鍊可壓延",
                        "磁性": "鐵磁材料",
                        "導電性": "否",
                        "密度": "1500克/cm³",
                        "熔點": "1500℃",
                        "光澤度": "高光"
                    }
                }
            }
        ]
    },
    "aggregations": {
        "dynamicproperty": {
            "doc_count": 56,
            "name": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                    {
                        "key": "密度",
                        "doc_count": 8,
                        "value": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "1000克/cm³",
                                    "doc_count": 4
                                },
                                {
                                    "key": "1500克/cm³",
                                    "doc_count": 3
                                },
                                {
                                    "key": "2000克/cm³",
                                    "doc_count": 1
                                }
                            ]
                        }
                    },
                    {
                        "key": "導熱性",
                        "doc_count": 8,
                        "value": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "較好",
                                    "doc_count": 6
                                },
                                {
                                    "key": "很好",
                                    "doc_count": 2
                                }
                            ]
                        }
                    },
                    {
                        "key": "熔點",
                        "doc_count": 8,
                        "value": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "2000℃",
                                    "doc_count": 3
                                },
                                {
                                    "key": "1000℃",
                                    "doc_count": 2
                                },
                                {
                                    "key": "1500℃",
                                    "doc_count": 2
                                },
                                {
                                    "key": "1600℃",
                                    "doc_count": 1
                                }
                            ]
                        }
                    },
                    {
                        "key": "延展性",
                        "doc_count": 7,
                        "value": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "易鍛物質,不需退火可錘鍊可壓延",
                                    "doc_count": 7
                                }
                            ]
                        }
                    },
                    {
                        "key": "光澤度",
                        "doc_count": 5,
                        "value": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "啞光",
                                    "doc_count": 3
                                },
                                {
                                    "key": "高光",
                                    "doc_count": 2
                                }
                            ]
                        }
                    },
                    {
                        "key": "導電性",
                        "doc_count": 5,
                        "value": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "是",
                                    "doc_count": 3
                                },
                                {
                                    "key": "否",
                                    "doc_count": 2
                                }
                            ]
                        }
                    },
                    {
                        "key": "抗氧化性",
                        "doc_count": 5,
                        "value": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "中",
                                    "doc_count": 4
                                },
                                {
                                    "key": "高",
                                    "doc_count": 1
                                }
                            ]
                        }
                    },
                    {
                        "key": "磁性",
                        "doc_count": 5,
                        "value": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "順磁材料",
                                    "doc_count": 4
                                },
                                {
                                    "key": "鐵磁材料",
                                    "doc_count": 1
                                }
                            ]
                        }
                    },
                    {
                        "key": "表面機理",
                        "doc_count": 5,
                        "value": {
                            "doc_count_error_upper_bound": 0,
                            "sum_other_doc_count": 0,
                            "buckets": [
                                {
                                    "key": "拉絲",
                                    "doc_count": 5
                                }
                            ]
                        }
                    }
                ]
            }
        }
    }
}

這樣就在返回搜索結果的同時返回了滿足條件的所有索引的動態屬性,把aggregations中的數據處理後返回給前端就可以實現類似京東的商品搜索效果。

 

接下來給出基於RestHighLevelClient的客戶端搜索實現:

@Test
    public void aggregate2() throws IOException {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchQuery("mainTitle","拉手"));

        BoolQueryBuilder boolQueryBuilder1 = QueryBuilders.boolQuery();
        boolQueryBuilder1.must(QueryBuilders.matchQuery("props.key","密度"));
        boolQueryBuilder1.must(QueryBuilders.matchQuery("props.value","2000克/cm³"));
        NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery("props",boolQueryBuilder1, ScoreMode.Total);
        searchSourceBuilder.query(nestedQueryBuilder);
        NestedAggregationBuilder level1Aggs = AggregationBuilders.nested("level1Agg","props");
        TermsAggregationBuilder propKeyAgg = AggregationBuilders.terms("keyAggs").field("props.key");
        level1Aggs.subAggregation(propKeyAgg);
        TermsAggregationBuilder propValAgg = AggregationBuilders.terms("valAggs").field("props.value");
        propKeyAgg.subAggregation(propValAgg);
        searchSourceBuilder.aggregation(level1Aggs);
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("smp-product");
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        if(RestStatus.OK == searchResponse.status()){
            //查詢結果
            SearchHits hits = searchResponse.getHits();
            log.info("hits={}",hits.getTotalHits());
            SearchHit[] arrs = hits.getHits();
            List<ESProduct> prods = new ArrayList<>(arrs.length);
            for(int i=0,len=arrs.length;i<len;i++){
                SearchHit hit = arrs[i];
                //ESProduct爲商品類
                ESProduct prod = JSON.parseObject(hit.getSourceAsString(),ESProduct.class);
                prods.add(prod);
            }
            Aggregations aggregations = searchResponse.getAggregations();
            //聚合結果處理
            ParsedNested level1Agg = aggregations.get("level1Agg");
            Aggregations keyAggs = level1Agg.getAggregations();
            Terms byAgeAggregation = keyAggs.get("keyAggs");
            List<FilterParamsDto> params = new ArrayList<>();
            for(Terms.Bucket buck : byAgeAggregation.getBuckets()) {
                Aggregations valAggs =  buck.getAggregations();
                Terms byValAggs =  valAggs.get("valAggs");
                FilterParamsDto param = new FilterParamsDto();
                param.setName(buck.getKeyAsString());
                List<String> vals = new ArrayList<>();
                param.setFilters(vals);
                for(Terms.Bucket bk : byValAggs.getBuckets()){
                    log.info("key: " + bk.getKeyAsString());
                    vals.add(bk.getKeyAsString());
                }
                params.add(param);
            }
        }
        log.info("finish");
    }

上面程序對應的ESProduct類定義如下:

@Getter
@Setter
@Document(indexName="smp-product",type="es-product",shards=3,replicas = 0)
@Mapping(mappingPath="mapping/es-product.json")
public class ESProduct extends BaseEntityMethods {

    @Field
    String id;

    /**
     * 商品名字
     */
    @Field(name="mainTitle")
    String mainTitle;

    @Field(name="subTitle")
    String subTitle;

    /**
     * 商品品牌
     */
    @Field(name="brandName")
    String brandName;

    /**
     * 一級類目名稱
     */
    @JsonIgnore
    @Field(name="level1Category")
    String level1Category;

    /**
     * 二級類目名稱
     */
    @JsonIgnore
    @Field(name="level2Category")
    String level2Category;

    /**
     * 三級類目名稱
     */
    @JsonIgnore
    @Field(name="level3Category")
    String level3Category;

    /**
     * 聚合關鍵詞使用
     */
    @Field(name="aggProperties")
    List<SearchProperty> aggProperties;

    /**
     * 檢索使用
     */
    @Field(name="searchProperties")
    Map<String,String> searchProperties;
}

PS:

1、本文使用的elasticsearch爲6.8版本

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章