• Github micro service
  • Github Mall front-end project -Vue

Retrieval service

Establishment of retrieval service basic environment

  • The final result

  • Results demonstrate

    • SkuTitle -> keyword
    • 2, ranking: saleCount (sales), hotScore (popularity), skuPrice (price)
    • 3, filtering: hasStock (available or not), skuPrice (price range), brandId (brandId can be selected), catalogId
    • 4. Aggregation: attrs (attributes)
    • Breadcrumb navigation
    • 6. Linkage between condition deletion and condition filtering

Setting up the Page Environment

  • Step 1: Search microservice imports dependencies

    <! <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <! --dev-tools--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>Copy the code

    Copy the search page index.html into your project and put it in the Templates directory

  • Step 2: Modify the local Hosts file

    Purpose To enable search.mall.com. Accessing search.mall.com is equivalent to accessing Nginx directly

    C:\Windows\System32\drivers\etc
    Copy the code

    After the modification is successful, save the hosts and visit search.mall.com to check the effect.

  • Step 3: Copy the static resources required for the page into the HTML /static/search directory in nginx (using xshell and XFTP)

    Nginx /conf/conf.d/mall.com/mall.com /static/ Docker restart nginx

  • Add /static/search/ to the href/SRC tag

    Add a new routing rule for the gateway service. Host is transferred to the search service and the gateway service is restarted

test

  • Ensure that the Search Search service Gateway services are successfully registered in the NACOS service registry

  • The nginx container configuration is modified and restarted

  • When the browser visits search.mall.com, the construction is complete if the following results appear

Retrieval business analysis

Retrieval parameter model analysis extraction

  • Three entry points for product search:

    • 1, Home page – Select the goods classification to access the goods retrieval (classification catalogId)

    • 2, enter the search keyword display search page (search keyword)

    • 3. Select the screening conditions to enter

  • Analysis of retrieval conditions

    • SkuTitle -> keyword

    • 2, ranking: saleCount (sales), hotScore (popularity), skuPrice (price)

    • 3, filtering: hasStock (available or not), skuPrice (price range), brandId (brandId can be selected), catalogId

    • 4. Aggregation: attrs (attributes)

      Catalog3Id =225&keyword= millet &hasStock=0/1&skuPrice=1_500&brandId=1&attrs= 1_Android: iOS&attrs=2_5 Sort: sort=saleCount_asc/desc, sort=skuPrice_asc/desc, sort=hostScore_asc/desc HasStock =0/1 skuPrice price range: skuPrice=1_500/_500/500_(1 to 500, less than 500, more than 500) BrandId =1&brandId=2 Attrs (attribute) : attrs= 1_Android: iOS&attrs=2_5. Inch, 6.5 inchCopy the code

Model analysis and extraction of retrieval results

  • According to the page content, extract the returned data

    SearchResult Total page number Total page number Current query result, all brands involved, all categories involved, and all attributes involvedCopy the code

Retrieval statement Building (DSL)

  • Start ES and Kibana containers

Query part statement

  • Write DSL statements in Kibana to clarify your thoughts

    GET the product / _search {" query ": {" bool" : {" must ": [{" match" : {" skuTitle ":" millet "}}], "filter" : [{" term ": { "catalogId": "225" } }, { "terms": { "brandId": [ "3", "10" ] } }, { "nested": { "path": "attrs", "query": { "bool": { "must": [ { "term": { "attrs.attrId": { "value": "13" } } }, { "terms": { "attrs.attrValue": [ "android" ] } } ] } } } }, { "term": { "hasStock": { "value": "true" } } }, { "range": { "skuPrice": { "gte": 100, "lte": 4000 } } } ] } }, "sort": [ { "skuPrice": { "order": "desc" } } ], "from": 0, "size": 1, "highlight": { "fields": {"skuTitle": {}}, "pre_tags": "<b style='color:red'>", "post_tags": "</b>" } }Copy the code

    If embedded attributes are nested, queries, aggregations, and analysis should be embedded

DSL aggregation analysis

ES Data Migration
  • Since there are some problems with the product index mapping in ES, we can create a new mall_product index, modify the mapping relationship, and migrate the original data into mall_product

    # data migration PUT mall_product {" the mappings ": {" properties" : {" skuId ": {" type" : "long"}, "spuId" : {" type ": "keyword" }, "skuTitle": { "type": "text", "analyzer": "ik_smart" }, "skuPrice": { "type": "keyword" }, "skuImg": { "type": "keyword" }, "saleCount": { "type": "long" }, "hasStock": { "type": "boolean" }, "hotScore": { "type": "long" }, "brandId": { "type": "long" }, "catalogId": { "type": "long" }, "brandName": { "type": "keyword" }, "brandImg": { "type": "keyword" }, "catalogName": { "type": "keyword" }, "attrs": { "type": "nested", "properties": { "attrId": { "type": "long" }, "attrName": { "type": "keyword" }, "attrValue": { "type": POST _reindex {"source": {"index": "product"}, "dest": GET mall_product/_search {"query": {"match_all": {}}Copy the code
Aggregate analysis
  • The final result

    # search & aggregation GET mall_product / _search {" query ": {" bool" : {" must ": [{" match" : {" skuTitle ":" millet "}}], "filter" : [ { "term": { "catalogId": "225" } }, { "terms": { "brandId": [ "3", "10" ] } }, { "nested": { "path": "attrs", "query": { "bool": { "must": [ { "term": { "attrs.attrId": { "value": "13" } } }, { "terms": { "attrs.attrValue": [ "android" ] } } ] } } } }, { "term": { "hasStock": { "value": "true" } } }, { "range": { "skuPrice": { "gte": 100, "lte": 4000 } } } ] } }, "sort": [ { "skuPrice": { "order": "desc" } } ], "from": 0, "size": 1, "highlight": { "fields": {"skuTitle": {}}, "pre_tags": "<b style='color:red'>", "post_tags": "</b>" }, "aggs": { "brand_agg": { "terms": { "field": "brandId", "size": 10 }, "aggs": { "brand_name_agg": { "terms": { "field": "brandName", "size": 10 } }, "brand_img_agg": { "terms": { "field": "brandImg", "size": 10 } } } }, "catalog_agg":{ "terms": { "field": "catalogId", "size": 10 }, "aggs": { "catalog_name_aggs": { "terms": { "field": "catalogName", "size": 10 } } } }, "attr_agg":{ "nested": { "path": "attrs" }, "aggs": { "attr_id_agg": { "terms": { "field": "attrs.attrId", "size": 10 }, "aggs": { "attr_name_agg": { "terms": { "field": "attrs.attrName", "size": 10 } }, "attr_value_agg": { "terms": { "field": "attrs.attrValue", "size": 10 } } } } } } } }Copy the code
  • The analysis process

    Current query result All brands involved Current query result All attributes involved Current query result All categories involvedCopy the code
    • All brands (same classification)

      GET mall_product/_search
      {
        "query": {
          "match_all": {}
        },
        "aggs": {
          "brand_agg": {
            "terms": {
              "field": "brandId",
              "size": 10
            }
          }
        }
      }
      Copy the code

    • Want to get the brand name and logo by the way

      GET mall_product/_search
      {
        "query": {
          "match_all": {}
        },
        "aggs": {
          "brand_agg": {
            "terms": {
              "field": "brandId",
              "size": 10
            },
            "aggs": {
              "brand_name_agg": {
                "terms": {
                  "field": "brandName",
                  "size": 10
                }
              },
               "brand_img_agg": {
                "terms": {
                  "field": "brandImg",
                  "size": 10
                }
              }
            }
          }
        }
      }
      Copy the code

    • All attributes under the current query result (*)

      • Attributes are nested, so aggregation analysis should also be aggregated

        GET mall_product/_search
        {
          "query": {
            "match_all": {}
          },
          "aggs": {
            "attr_agg":{
              "nested": {
                "path": "attrs"
              },
              "aggs": {
                "attr_id_agg": {
                  "terms": {
                    "field": "attrs.attrId",
                    "size": 10
                  },
                  "aggs": {
                    "attr_name_agg": {
                      "terms": {
                        "field": "attrs.attrName",
                        "size": 10
                      }
                    },
                    "attr_value_agg": {
                      "terms": {
                        "field": "attrs.attrValue",
                        "size": 10
                      }
                    }
                  }
                }
              }
            }
          }
        }
        Copy the code

Code implementation

The SearchRequest build

  • Java implementations need DSL statements to dynamically build queries

    • retrieve

      --bool query
        --must
          --term
        --filter
        	--term
        	--terms
        	--term
        	--range
        	--nested
        	  --bool
        	  	--must
        	  	  --term
        	  	  --term
      Copy the code
    • Paging, sorting, highlighting

    • The aggregation

      --brand_agg
        --brand_name_agg
        --brand_img_agg
      --catalog_agg
        --catalog_name_agg
      --nestedAttr_agg
        --attr_id_agg
        	--attr_name_agg
        	--attr_value_agg
      Copy the code

  • Test that the retrieval statement build is correct

    • The first:

      • Postman Simple request (keyword, catalog3Id)

      • Print the searchSourceBuilder and format it using the online JSON formatting tool

      • If the statement is constructed correctly, you can copy it directly to Kibana for query

    • The second:

      • Complex filtering (attributes attrs, price range)

  • Test aggregate statement

    • Postman simulates requests

    • Print out the statement and copy it to Kibana

SearchResponse analysis & encapsulation

  • Encapsulate the result returned by ES

    1. All returned commodities queried 2. All attributes of all current commodities 3. All brand information of all current commodities 4Copy the code

Page rendering

Page basic data rendering

  • Retrieval data display

  • Brush selection condition selection, request path stitching

    #&quot; brandId&quot; For "brandId" double quotation marks before and after th: href = "${' javascript: searchProducts (& quot; brandId&quot; ,'+brand.brandId+')'}Copy the code

  • Keyword search

    The search criteria are displayed

  • Paging data rendering

  • Sorting effect

    • The sorting

    • The sorting field is displayed (after page skipping)

  • Breadcrumb navigation

  • Conditional filtering linkage