ES 自动纠错补全功能

828 阅读4分钟

一、前言

本文目的:实践熟悉 ES 下自动纠错补全功能。

需求搜索框里进行输入时,实现如下:

  • 自动补全
  • 自动纠错
  • 自动推荐

举个栗子:

2022-02-1218-58-20.png

为了完成这个需求,实现步骤如下:

  1. 创建 suggest 索引
  2. 将商品数据写入 suggest 索引
  3. 查询 suggest 索引

为了提供搜索,需要把商品数据也写入到 suggest 索引里。

suggest 索引

suggest 索引用来存储和用户输入自动补全、拼写纠错、搜索推荐等相关的数据索引。

创建 suggest 索引如下:

PUT /sku_suggest
{
    "settings":{
        "number_of_shards":3,
        "number_of_replicas":1,
        "analysis":{
            "analyzer":{
                "ik_and_pinyin_analyzer":{
                    "type":"custom",
                    "tokenizer":"ik_smart",
                    "filter":"my_pinyin"
                }
            },
            "filter":{
                "my_pinyin":{
                    "type":"pinyin",
                    "keep_first_letter":true,
                    "keep_full_pinyin":true,
                    "keep_original":true,
                    "remove_duplicated_term":true
                }
            }
        }
    },
    "mappings":{
        "properties":{
            "word1":{
                "type":"completion",
                "analyzer":"ik_and_pinyin_analyzer"
            },
            "word2":{
                "type":"text"
            }
        }
    }
}

字段详解如下:

  • word1:用来做自动补全,对应 ES 中的 completion 数据类型。

对应 对应文档

  • analyzer:定义了 ik_and_pinyin_analyzer ,同时使用了 IK 分词器和 pinyin 分词器。



二、搜索数据写入

将商品名写入 suggest 索引里的 word1 字段:

  • 自动补全:用 IKpinyin 做分词,建立分词后的倒排索引
  • 自动纠错:用 IKpinyin 做分词,建立分词后的倒排索引
  1. 创建索引
PUT /sku_suggest
{
    "settings": {
        "number_of_shards": 3,
        "number_of_replicas": 0,
        "analysis": {
            "analyzer": {
                "ik_and_pinyin_analyzer": {
                    "type": "custom",
                    "tokenizer": "ik_smart",
                    "filter": "my_pinyin"
                }
            },
            "filter": {
                "my_pinyin": {
                    "type": "pinyin",
                    "keep_first_letter": true,
                    "keep_full_pinyin": true,
                    "keep_original": true,
                    "remove_duplicated_term": true
                }
            }
        }
    },
    "mappings": {
        "properties": {
            "word1": {
                "type": "completion",
                "analyzer": "ik_and_pinyin_analyzer"
            },
            "word2": {
                "type": "text"
            }
        }
    }
}

响应如下:
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "sku_suggest"
}
  1. 造数据:请求接口
POST http://47.99.221.206:8080/api/mockData/mockData3
{
    "indexName": "sku_suggest",
    "batchSize": 20,
    "batchTimes": 100
}


请求响应:
{
    "success": true,
    "data": {
        "startTime": "2022-04-09 21:17:46",
        "endTime": "2022-04-09 21:18:06",
        "totalCount": 2000,
        "elapsedSeconds": 19,
        "perSecond": 105
    },
    "errorCode": null,
    "errorMessage": null
}
  1. 查看索引信息
# 查看索引下文档的个数
GET /_cat/count/sku_suggest?v&h=count

count
8200

# 查看索引下文档个数、索引占用的磁盘空间等
GET /_cat/indices/sku_suggest?v

health status index       uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   sku_suggest P2r9t1UsSS6guT5m-sD2DQ   3   0       8200            0      1.8gb          1.8gb

2022-04-0921-25-13.png

2022-04-0921-25-52.png

为什么 career_plan_sku_suggest 索引占用磁盘空间很大?原因有 2:

  1. 插入的数据比正常数据长很多
猫窝宠物窝垫可拆洗四季猫屋公主猫床冬季保暖宠物床小猫窝猫用品
猫零食路斯猫薄荷猫饼干鸡肉猫磨牙小鱼饼干幼猫零食宠物猫咪零食
猫窝冬可拆洗猫睡袋四季蒙古包 汉堡猫屋猫房子秋冬宠物猫咪用品
  1. 自定义了 ik_and_pinyin_analyzer 分词器,分解出大量 pinyin 和词
GET /sku_suggest/_analyze
{
    "text": "猫窝宠物窝垫可拆洗四季猫屋公主猫床冬季保暖宠物床小猫窝猫用品",
    "analyzer": "ik_and_pinyin_analyzer"
}

分解出的数据很多:

2022-04-0921-21-07.png



三、基于 suggest 查询

(1)自动补全查询

举个栗子:

2022-02-1218-58-20.png

  1. 测试1:补全华为
GET http://47.99.221.206:8080/api/common/autoComplete
{
    "indexName": "sku_suggest",
    "fieldName": "word1",
    "text": "华为",
    "count": 10
}

响应内容:
{
    "success": true,
    "data": [
        "Huawei/华为 Mate 9 32/64GB【0:00限量抢 买赠碎屏保】年度旗舰",
        "Huawei/华为 P9 plus【双12购机送288元好礼】徕卡双摄智能手机",
        "华为honor/荣耀 V8 大屏4G智能拍照手机指纹解锁官方正品",
        "华为honor/荣耀 畅玩5 移动全网通版智能拍照手机 全新官方正品",
        "华为honor/荣耀 畅玩5A 4G智能手机 大屏官方正品",
        "华为honor/荣耀 畅玩5C 全网通4G智能手机超长待机官方正品 现货",
        "华为honor/荣耀 畅玩5x 4G智能手机官方大屏正品",
        "华为honor/荣耀 畅玩6X 全网通智能手机官方正品4G大内存旗舰手机",
        "华为honor/荣耀 荣耀 NOTE 8 4G大屏智能手机官方正品",
        "华为honor/荣耀 荣耀7i全网通智能手机 官方正品"
    ],
    "errorCode": null,
    "errorMessage": null
}
  1. 测试2:补全 huawei
GET http://47.99.221.206:8080/api/common/autoComplete
{
    "indexName": "sku_suggest",
    "fieldName": "word1",
    "text": "huawei",
    "count": 10
}

响应内容:
{
    "success": true,
    "data": [
        "华为honor/荣耀 畅玩5 移动全网通版智能拍照手机 全新官方正品",
        "华为honor/荣耀 畅玩5A 4G智能手机 大屏官方正品",
        "华为honor/荣耀 畅玩5C 全网通4G智能手机超长待机官方正品 现货"
    ],
    "errorCode": null,
    "errorMessage": null
}


(2)自动纠错查询

举个栗子: huawei wifi -> huwei wiff

2022-02-1219-10-15.png

  1. 测试1:纠错 huwei
GET http://47.99.221.206:8080/api/common/spellingCorrection
{
    "indexName": "sku_suggest",
    "fieldName": "word2",
    "text": "huwei"
}

响应内容:
{
    "success": true,
    "data": "huawei",
    "errorCode": null,
    "errorMessage": null
}
  1. 测试2:纠错 纠错wiff
GET http://47.99.221.206:8080/api/common/spellingCorrection
{
    "indexName": "sku_suggest",
    "fieldName": "word2",
    "text": "wiff"
}

响应内容:
{
    "success": true,
    "data": "wifi",
    "errorCode": null,
    "errorMessage": null
}