• 基于 Elasticsearch 聚合搜索实现电商筛选查询功能


    前言

    在网上购物时,首先是需要输入关键字检索商品,当进入搜索页时,一般夺会有一个筛选,方便用户进一步缩小商品范围,例如某宝、某东,其上面的商品都是亿万级别的体量,从下图可以得出,筛选条件中包括价格、品牌、商品规格属性(功效、净含量...)等,并且不同的搜索条件展示出来的筛选内容也是截然不同的,在这里介绍如何基于 Elasticsearch 的聚合搜索实现此功能

    某东

    某宝

    筛选条件

    实现筛选过滤功能,首先得对 dsl 语句有一定的了解(小伙伴自行补课~)

    1. 创建索引

    在这里有一点要注意的是其中 attributes 是用了 nested 类型
    不了解的小伙伴请看这位大佬的文章 干货 | Elasticsearch Nested类型深入详解

    # 创建索引
    PUT product_index
    {
        "settings": {
            "number_of_shards": 1,
            "number_of_replicas": 0
        },
        "mappings": {
            "properties": {
                "id": {
                    "type": "long"
                },
                "name": {
                    "type": "text"
                },
                "brandId": {
                    "type": "keyword"
                },
                "brand": {
                    "type": "keyword"
                },
                "price": {
                    "type": "double"
                },
                "attributes": {
                    "type": "nested",
                    "properties": {
                        "attrKeyId": {
                            "type": "keyword"
                        },
                        "attrKeyName": {
                            "type": "keyword"
                        },
                        "attrValueName": {
                            "type": "keyword"
                        }
                    }
                }
            }
        }
    }
    
    1. 创建数据
    # 创建数据
    PUT /product_index/_bulk
    {"index": {}}
    {"id ":1,"name":"日系短袖","brandId":"10","brand":"优衣库","price":99.99,"attributes":[{"attrKeyId":"1","attrKeyName":"适用季节","attrValueName":"春季"},{"attrKeyId":"2","attrKeyName":"风格","attrValueName":"日系"},{"attrKeyId":"3","attrKeyName":"人群","attrValueName":"青年"}]}
    {"index": {}}
    {"id ":2,"name":"韩版短袖","brandId":"20","brand":"Kirsh","price":199.99,"attributes":[{"attrKeyId":"1","attrKeyName":"适用季节","attrValueName":"夏季"},{"attrKeyId":"2","attrKeyName":"风格","attrValueName":"韩系"},{"attrKeyId":"3","attrKeyName":"人群","attrValueName":"少年"}]}
    {"index": {}}
    {"id ":3,"name":"美系短袖","brandId":"30","brand":"Nike","price":299.99,"attributes":[{"attrKeyId":"1","attrKeyName":"适用季节","attrValueName":"秋季"},{"attrKeyId":"2","attrKeyName":"风格","attrValueName":"美系"},{"attrKeyId":"3","attrKeyName":"人群","attrValueName":"中年"}]}
    {"index": {}}
    {"id ":4,"name":"国产短袖","brandId":"40","brand":"安踏","price":399.99,"attributes":[{"attrKeyId":"1","attrKeyName":"适用季节","attrValueName":"冬季"},{"attrKeyId":"2","attrKeyName":"风格","attrValueName":"国潮"},{"attrKeyId":"3","attrKeyName":"人群","attrValueName":"青少年"}]}
    {"index": {}}
    {"id ":5,"name":"中国短袖","brandId":"40","brand":"安踏","price":499.99,"attributes":[{"attrKeyId":"1","attrKeyName":"适用季节","attrValueName":"夏季"},{"attrKeyId":"2","attrKeyName":"风格","attrValueName":"国潮"},{"attrKeyId":"3","attrKeyName":"人群","attrValueName":"青少年"}]}
    
    1. 根据搜索内容找出全部可筛选条件

    模拟场景:输入“短袖”进行搜索,找到可筛选的 品牌(brand)&商品规格属性(attributes) 条件

    # 根据搜索内容找出全部可筛选条件
    GET /product_index/_search
    {
      "query": {
        "match": {
          "name": "短袖"
        }
      }, 
      "size": 0, 
      "aggs": {
          "brandId": {
            "terms": {
              "field": "brandId"
            },
            "aggs": {
              "brand": {
                "terms": {
                  "field": "brand"
                }
              }
            }
          },
          "attra": {
            "nested": {
              "path": "attributes"
            },
            "aggs": {
              "attrKeyId": {
                "terms": {
                "field": "attributes.attrKeyId"
              },
              "aggs": {
                "attrKeyName": {
                  "terms": {
                    "field": "attributes.attrKeyName"
                  }
                },
                "attrValueName": {
                  "terms": {
                    "field": "attributes.attrValueName"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    品牌聚合结果:

    "brandId" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "40",
              "doc_count" : 2,
              "brand" : {
                "doc_count_error_upper_bound" : 0,
                "sum_other_doc_count" : 0,
                "buckets" : [
                  {
                    "key" : "安踏",
                    "doc_count" : 2
                  }
                ]
              }
            },
            {
              "key" : "10",
              "doc_count" : 1,
              "brand" : {
                "doc_count_error_upper_bound" : 0,
                "sum_other_doc_count" : 0,
                "buckets" : [
                  {
                    "key" : "优衣库",
                    "doc_count" : 1
                  }
                ]
              }
            },
            {
              "key" : "20",
              "doc_count" : 1,
              "brand" : {
                "doc_count_error_upper_bound" : 0,
                "sum_other_doc_count" : 0,
                "buckets" : [
                  {
                    "key" : "Kirsh",
                    "doc_count" : 1
                  }
                ]
              }
            },
            {
              "key" : "30",
              "doc_count" : 1,
              "brand" : {
                "doc_count_error_upper_bound" : 0,
                "sum_other_doc_count" : 0,
                "buckets" : [
                  {
                    "key" : "Nike",
                    "doc_count" : 1
                  }
                ]
              }
            }
          ]
        }
    

    商品规格属性聚合结果:

    "attr" : {
          "doc_count" : 15,
          "attrKeyId" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "1",
                "doc_count" : 5,
                "attrKeyName" : {
                  "doc_count_error_upper_bound" : 0,
                  "sum_other_doc_count" : 0,
                  "buckets" : [
                    {
                      "key" : "适用季节",
                      "doc_count" : 5
                    }
                  ]
                },
                "attrValueName" : {
                  "doc_count_error_upper_bound" : 0,
                  "sum_other_doc_count" : 0,
                  "buckets" : [
                    {
                      "key" : "夏季",
                      "doc_count" : 2
                    },
                    {
                      "key" : "冬季",
                      "doc_count" : 1
                    },
                    {
                      "key" : "春季",
                      "doc_count" : 1
                    },
                    {
                      "key" : "秋季",
                      "doc_count" : 1
                    }
                  ]
                }
              },
              {
                "key" : "2",
                "doc_count" : 5,
                "attrKeyName" : {
                  "doc_count_error_upper_bound" : 0,
                  "sum_other_doc_count" : 0,
                  "buckets" : [
                    {
                      "key" : "风格",
                      "doc_count" : 5
                    }
                  ]
                },
                "attrValueName" : {
                  "doc_count_error_upper_bound" : 0,
                  "sum_other_doc_count" : 0,
                  "buckets" : [
                    {
                      "key" : "国潮",
                      "doc_count" : 2
                    },
                    {
                      "key" : "日系",
                      "doc_count" : 1
                    },
                    {
                      "key" : "美系",
                      "doc_count" : 1
                    },
                    {
                      "key" : "韩系",
                      "doc_count" : 1
                    }
                  ]
                }
              },
              {
                "key" : "3",
                "doc_count" : 5,
                "attrKeyName" : {
                  "doc_count_error_upper_bound" : 0,
                  "sum_other_doc_count" : 0,
                  "buckets" : [
                    {
                      "key" : "人群",
                      "doc_count" : 5
                    }
                  ]
                },
                "attrValueName" : {
                  "doc_count_error_upper_bound" : 0,
                  "sum_other_doc_count" : 0,
                  "buckets" : [
                    {
                      "key" : "青少年",
                      "doc_count" : 2
                    },
                    {
                      "key" : "中年",
                      "doc_count" : 1
                    },
                    {
                      "key" : "少年",
                      "doc_count" : 1
                    },
                    {
                      "key" : "青年",
                      "doc_count" : 1
                    }
                  ]
                }
              }
            ]
          }
        }
    

    得到了以上结果即可通过服务端组装数据(这里就不在深入了~)

    筛选查询

    经过以上步骤可以得到搜索时的全部筛选条件,那么下一步就是带入筛选条件进行查询商品了,话不多说咱们开始

    1. 条件搜索

    模拟场景:搜索关键词:“短袖”,品牌为“优衣库”,适用季节为“春季”的商品
    根据模拟场景可得出以下参数

    1. keyword (关键词)
    2. brandId (品牌id)
    3. attrKeyId (属性id)
    4. attrValueName (属性值)

    其中 attr 可能会选择很多,若是业务场景中每个属性是单选的情况下,推荐使用 k,v 的形式接收规格属性参数

    # 根据筛选条件查询商品
    GET /product_index/_search
    {
        "query": {
            "bool": {
                "must": [
                    {
                        "match": {
                            "name": "短袖"
                        }
                    }
                ],
                "filter": [
                    {
                        "bool": {
                            "must": [
                                {
                                    "term": {
                                        "brandId": {
                                            "value": "10"
                                        }
                                    }
                                },
                                {
                                    "nested": {
                                        "path": "attributes",
                                        "query": {
                                            "bool": {
                                                "must": [
                                                    {
                                                        "term": {
                                                            "attributes.attrKeyId": {
                                                                "value": "1"
                                                            }
                                                        }
                                                    },
                                                    {
                                                        "term": {
                                                            "attributes.attrValueName": {
                                                                "value": "春季"
                                                            }
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        }
    }
    
    

    搜索结果:

    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1,
          "relation" : "eq"
        },
        "max_score" : 0.17402273,
        "hits" : [
          {
            "_index" : "product_index",
            "_type" : "_doc",
            "_id" : "_GtUzXoBSEC8FU4FyZf0",
            "_score" : 0.17402273,
            "_source" : {
              "id " : 1,
              "name" : "日系短袖",
              "brandId" : "10",
              "brand" : "优衣库",
              "price" : 99.99,
              "attributes" : [
                {
                  "attrKeyId" : "1",
                  "attrKeyName" : "适用季节",
                  "attrValueName" : "春季"
                },
                {
                  "attrKeyId" : "2",
                  "attrKeyName" : "风格",
                  "attrValueName" : "日系"
                },
                {
                  "attrKeyId" : "3",
                  "attrKeyName" : "人群",
                  "attrValueName" : "青年"
                }
              ]
            }
          }
        ]
      }
    }
    
    

    若将brandId替换成 20(或是替换任意参数),结果为:

    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 0,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      }
    }
    
    

    由此可得出筛选过滤查询以实现啦~

    总结

    这是基于Es聚合实现电商筛选搜索的思路,如果老哥们有好的建议或是意见的话欢迎在评论区留言哦~

  • 相关阅读:
    mplayerww-34106 gcc-4.5.1
    再更新ww的mingw MinGW-full-20101119
    mplayer-ww-37356 compile with mingw gcc 4.5.1 修复无法播放wmv
    CodeBlocks_20160621_rev10868_gcc5.3.0
    更新ww的mingw MinGW-full-20101119
    HTML5学习笔记(六)web worker
    HTML5学习笔记(五)存储
    HTML5学习笔记(四)语义元素
    HTML5学习笔记(三)新属性、功能
    HTML5学习笔记(二)新元素和功能
  • 原文地址:https://www.cnblogs.com/z-coding/p/15045724.html
Copyright © 2020-2023  润新知