zoukankan      html  css  js  c++  java
  • ES Suggester 搜索自动补全

    需求

    将商品表数据全量更新至ES索引
    商品索引支持Suggester自动补全,支持过滤商品enable和delete_status状态,只筛选启用且未删除的商品
    Suggester与普通搜索区别:ES将Suggest机器依赖的字段放在堆内存,实现近实时的搜索提示功能

    es安装ik分词插件

    ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.7.0/elasticsearch-analysis-ik-7.7.0.zip

    配置logstash配置文件

    input {
        stdin {
        }
        jdbc {
          # 连接的数据库地址和哪一个数据库,指定编码格式,禁用SSL协议,设定自动重连
          jdbc_connection_string => "jdbc:mysql://{你的MySQL}:3306/shop-server?characterEncoding=UTF-8&useSSL=false&autoReconnect=true"
          # 你的账户密码
          jdbc_user => "{你的用户}"
          jdbc_password => "{你的密码}"
          # 连接数据库的驱动包,建议使用绝对地址
          jdbc_driver_library => "/data/logstash-6.4.0/bin/mysql/mysql-connector-java-5.1.22-bin.jar"
          # 这是不用动就好
          jdbc_driver_class => "com.mysql.jdbc.Driver"
          jdbc_paging_enabled => "true"
          jdbc_page_size => "2000"
    
              #处理中文乱码问题
          codec => plain { charset => "UTF-8"}
    
          #使用其它字段追踪,而不是用时间
          use_column_value => true
          #追踪的字段
          tracking_column => app_goods_id
          record_last_run => true
            statement => "SELECT
            g.app_goods_id,
            g.goods_id,
            g.goods_name,
            g.goods_name AS suggest,
            g.collect_count,
            g.sale,
            g.alone_price,
            g.enable,
            g.delete_status,
             (SELECT GROUP_CONCAT( goods_type_id ) FROM db_goods_type_link WHERE goods_id = g.goods_Id ) AS goods_type_id,
            CASE
                    WHEN g.alone_price > 301 THEN
                    100
                    WHEN g.alone_price > 101 THEN
                    300
                    WHEN g.alone_price > 51 THEN
                    500
                    WHEN g.alone_price > 0 THEN
                    400 ELSE 0
            END price_score,
            CASE
                    b.brand_level
                    WHEN 1 THEN
                    500
                    WHEN 2 THEN
                    300
                    WHEN 3 THEN
                    100
                    WHEN 4 THEN
                    0 ELSE 0
            END brand_score
            FROM
            db_app_goods g
            LEFT JOIN db_brand b ON g.brand_id = b.brand_id
            LIMIT 2000"
    
          #上一个sql_last_value值的存放文件路径, 必须要在文件中指定字段的初始值
          last_run_metadata_path => "/data/logstash-6.4.0/bin/mysql/goods.log"
    
          jdbc_default_timezone => "Asia/Shanghai"
    
          #statement_filepath => "mysql/jdbc.sql"
    
    
          #是否清除 last_run_metadata_path 的记录,如果为真那么每次都相当于从头开始查询所有的数据库记录
          clean_run => false
    
          # 这是控制定时的,重复执行导入任务的时间间隔,第一位是分钟
          schedule => "* */1 * * *"
          type => "jdbc"
        }
    }
    
    
    filter {
        json {
            source => "message"
            remove_field => ["message"]
        }
    }
    
    
    output {
        elasticsearch {
            # 要导入到的Elasticsearch所在的主机
            hosts => "127.0.0.1:9200"
            # 要导入到的Elasticsearch的索引的名称
            index => "goods"
            # 类型名称(类似数据库表名)
            #document_type => "appgood"
            # 主键名称(类似数据库主键)
            document_id => "%{app_goods_id}"
            # es 账号
            user => {你的ES用户}
            password => {你的ES密码}
            # 这里配置为当前logstash的相对路径,该文件配置了输出的Mapping
            template => "mysql/goods_mapping.json"
            template_name => "goods"
            template_overwrite => true
    
        }
    
        stdout {
            # JSON格式输出
            codec => json_lines
        }
    }

    创建商品索引映射goods_mapping.json

    {
            "template": "goods",
            "settings": {
                    "index.refresh_interval": "1s"
            },
            "index_patterns": ["goods"],
            "mappings": {
                    "properties": {
                            "suggest": {
                                    "type": "completion",
                                    "analyzer": "ik_smart",
                                    "search_analyzer": "ik_smart",
                                    "contexts": [{
                                                    "name": "enable_cat",
                                                    "type": "category",
                                                    "path": "enable"
                                            },
                                            {
                                                    "name": "delete_status_cat",
                                                    "type": "category",
                                                    "path": "delete_status"
                                            }
                                    ]
                            },
                            "goods_name": {
                                    "type": "text",
                                    "analyzer": "ik_max_word",
                                    "search_analyzer": "ik_smart"
                            },
                            "goods_type_id": {
                                    "type": "keyword"
                            },
                            "app_goods_id": {
                                    "type": "long"
                            },
                            "goods_id": {
                                    "type": "long"
                            },
                            "collect_count": {
                                    "type": "integer"
                            },
                            "sale": {
                                    "type": "integer"
                            },
                            "alone_price": {
                                    "type": "double"
                            },
                            "brand_score": {
                                    "type": "integer"
                            },
                            "enable": {
                                    "type": "keyword"
                            },
                            "delete_status" :{
                                    "type": "keyword"
                            }
                    }
            }
    }

    使用logstash -f {goods配置文件}启动logstash,logstash将自动从数据库查询并以Mapping创建索引

    查看索引是否映射成功
    GET goods_dev/_mapping
    结果:

    {
      "goods_dev" : {
        "mappings" : {
          "properties" : {
            "@timestamp" : {
              "type" : "date"
            },
            "@version" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            },
            "alone_price" : {
              "type" : "double"
            },
            "app_goods_id" : {
              "type" : "long"
            },
            "brand_score" : {
              "type" : "integer"
            },
            "collect_count" : {
              "type" : "integer"
            },
            "delete_status" : {
              "type" : "keyword"
            },
            "enable" : {
              "type" : "keyword"
            },
            "goods_id" : {
              "type" : "long"
            },
            "goods_name" : {
              "type" : "text",
              "analyzer" : "ik_max_word",
              "search_analyzer" : "ik_smart"
            },
            "goods_type_id" : {
              "type" : "keyword"
            },
            "price_score" : {
              "type" : "long"
            },
            "sale" : {
              "type" : "integer"
            },
            "suggest" : {
              "type" : "completion",
              "analyzer" : "ik_smart",
              "preserve_separators" : true,
              "preserve_position_increments" : true,
              "max_input_length" : 50,
              "contexts" : [
                {
                  "name" : "enable_cat",
                  "type" : "CATEGORY",
                  "path" : "enable"
                },
                {
                  "name" : "delete_status_cat",
                  "type" : "CATEGORY",
                  "path" : "delete_status"
                }
              ]
            },
            "type" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword",
                  "ignore_above" : 256
                }
              }
            }
          }
        }
      }
    }

    使用前缀ContextComplitationSuggester进行联想词查询

    POST goods_dev/_search?pretty
    {
      "_source": "suggest",
      "suggest": {
        "my-suggest":{
          "prefix":"肌肤",
          "completion":{
            "field":"suggest",
            "skip_duplicates":true,
            "size":10,
            "contexts":{
              "enable_cat":{
                 "context":1
              },
              "delete_status_cat":{
                "context":0
              }
            }
          }
        }
      }
    }

    结果:

    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 0,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      },
      "suggest" : {
        "my-suggest" : [
          {
            "text" : "肌肤",
            "offset" : 0,
            "length" : 2,
            "options" : [
              {
                "text" : "“肌肤吸尘器123”香港CHICELAN槿念烟酰胺磨砂沐浴露温和双效去角质一瓶=沐浴露+磨砂膏",
                "_index" : "goods_dev",
                "_type" : "_doc",
                "_id" : "1323938082604585019",
                "_score" : 1.0,
                "_source" : {
                  "suggest" : "“肌肤吸尘器123”香港CHICELAN槿念烟酰胺磨砂沐浴露温和双效去角质一瓶=沐浴露+磨砂膏"
                },
                "contexts" : {
                  "enable_cat" : [
                    "1"
                  ]
                }
              },
              {
                "text" : "“肌肤吸尘器”香港CHICELAN槿念烟酰胺磨砂沐浴露温和双效去角质一瓶=沐浴露+磨砂膏",
                "_index" : "goods_dev",
                "_type" : "_doc",
                "_id" : "1323894411586834447",
                "_score" : 1.0,
                "_source" : {
                  "suggest" : "“肌肤吸尘器”香港CHICELAN槿念烟酰胺磨砂沐浴露温和双效去角质一瓶=沐浴露+磨砂膏"
                },
                "contexts" : {
                  "delete_status_cat" : [
                    "0"
                  ]
                }
              }
            ]
          }
        ]
      }
    }

    使用SpringDataElasticsearch进行JavaAPI查询

    新建一个固定suggest查询对象,该对象构建一个查询context,类似于上面的

    "contexts":{
              "enable_cat":{
                 "context":1
              },
              "delete_status_cat":{
                "context":0
              }
            }
    /**
         * 固定的suggest查询对象
         */
        private static  Map<String, List<? extends ToXContent>> SUGGESTION_CONTEXT = null;
        static {
            CategoryQueryContext enableCat = CategoryQueryContext.builder().setCategory("1").build();
            CategoryQueryContext deleteStatusCat = CategoryQueryContext.builder().setCategory("0").build();
            Map<String, List<? extends ToXContent>> contexts = new HashMap<>();
            List<CategoryQueryContext> list = new ArrayList<>(1);
            list.add(enableCat);
            contexts.put("enable_cat", list);
            List<CategoryQueryContext> list2 = new ArrayList<>(1);
            list2.add(deleteStatusCat);
            contexts.put("delete_status_cat",list2);
            SUGGESTION_CONTEXT = contexts;
        }

    根据关键字联想查询方法

        @Override
        public List<String> associate(String keyword) {
            //使用suggest进行标题联想
            CompletionSuggestionBuilder suggest = SuggestBuilders.completionSuggestion("suggest").prefix(keyword).skipDuplicates(true).size(10).contexts(SUGGESTION_CONTEXT);
            SuggestBuilder suggestBuilder = new SuggestBuilder();
            suggestBuilder.addSuggestion("goodsNameSuggest",suggest);
    
            //查询
            SearchResponse goodsNameSuggestResp = elasticsearchRestTemplate.suggest(suggestBuilder, goodsIndexName);
            Suggest.Suggestion<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> goodsNameSuggest = goodsNameSuggestResp
                    .getSuggest().getSuggestion("goodsNameSuggest");
            //处理返回
            List<String> collect = goodsNameSuggest.getEntries().stream().map(x -> x.getOptions().stream().map(y->y.getText().toString()).collect(Collectors.toList())).findFirst().get();
            return CollectionUtils.isEmpty(collect)?Collections.emptyList():collect;
        }

    接口测试

    接口传递keyword关键字"韩版",返回

    {
      "code": 200,
      "msg": "操作成功",
      "timestamp": "1605173186443",
      "data": [
        "韩版时尚中长款衬衫 Because-t2041",
        "韩版淑女纯色休闲裤 Holicholic-sp26265",
        "韩版简约时尚连衣裙 Happy10-ds1009573",
        "韩版简约纯色衬衫 Holicholic-t26070",
        "韩版简约经典半身裙 Maybe-baby-sp30591",
        "韩版简约经典女裤套装 Holicholic-ds26260",
        "韩版纯色休闲T恤 Holicholic-t26074"
      ]
    }
    作者:老王_KICHUN
    链接:https://www.jianshu.com/p/c78011dd9028
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    Nginx的配置文件详解(超详细)
    淘宝地址爬取及UI展示
    点击观看
    winform picturebox设置布局样式
    vs的一个不经常用的快捷键
    C# 开发windows服务
    winform窗体置顶
    C# mysql set和enum属性字段的读取和添加
    winform窗体绑定监控键盘事件
    html5创建的sqlite存放为止以及在手机中的位置
  • 原文地址:https://www.cnblogs.com/it-deepinmind/p/14539066.html
Copyright © 2011-2022 走看看