zoukankan      html  css  js  c++  java
  • elasticsearch-搜索之中英文搜索(四)

    需求

    雪花啤酒  需要搜索雪花、啤酒 、雪花啤酒、xh、pj、xh啤酒、雪花pj

    ik导入

    参考https://www.cnblogs.com/LQBlog/p/10443862.html,不需要修改源码步骤就行

    拼音分词器导入

    跟ik一样 下载下来打包移动到es plugins 目录名字改为pinyin https://github.com/medcl/elasticsearch-analysis-pinyin

    测试

    get请求:http://127.0.0.1:9200/_analyze

    body:

    {
    "analyzer":"pinyin",
    "text":"雪花啤酒"
    }

    响应:

    {
        "tokens": [
            {
                "token": "xue",
                "start_offset": 0,
                "end_offset": 0,
                "type": "word",
                "position": 0
            },
            {
                "token": "xhpj",
                "start_offset": 0,
                "end_offset": 0,
                "type": "word",
                "position": 0
            },
            {
                "token": "hua",
                "start_offset": 0,
                "end_offset": 0,
                "type": "word",
                "position": 1
            },
            {
                "token": "pi",
                "start_offset": 0,
                "end_offset": 0,
                "type": "word",
                "position": 2
            },
            {
                "token": "jiu",
                "start_offset": 0,
                "end_offset": 0,
                "type": "word",
                "position": 3
            }
        ]
    }

    说明导入成功

    测试中文加拼音搜索

    自定义mapping和自定义分词器

    put请求:http://127.0.0.1:9200/opcm3

    body:

    {
        "settings": {
            "analysis": {
                "analyzer": {
                    "ik_pinyin_analyzer": {//自定义一个分词器名字叫ik_pinyin_analyzer
                        "type": "custom",//表示自定义分词器
                        "tokenizer": "ik_smart",//使用ik分词 ik_smart为粗粒度分词 ik_max_word为最细粒度分词
                        "filter": ["my_pinyin"]//分词后结果 交给过滤器再次分词
                    },
                    "onlyOne_analyzer": {
                        "tokenizer": "onlyOne_pinyin"
                    }
                },
                "tokenizer": {
                    "onlyOne_pinyin": {
                        "type": "pinyin",
                        "keep_separate_first_letter": "true",
                        "keep_full_pinyin":"false"
                    }
                },"filter": {
                    "my_pinyin": {//定义过滤器
                        "type": "pinyin",
                        "keep_joined_full_pinyin": true,//分词的时候词组首字母分词后组合 如:雪花 分词:xuehua  xh
                        "keep_separate_first_letter": true//分词的时候支持首字母不单独分词如:会分词xue hua xuehua  xh  x,h
                        "none_chinese_pinyin_tokenize": true//xh 分词为x,h,xh
    
                    }
                }
            }
    
        },
        "mappings": {
            "doc": {
                "properties": {
                    "productName": {
                        "type": "text",
                        "analyzer": "ik_pinyin_analyzer",//指定分词索引为自定义分词 中文分词后再通过filter交给pinyin分词
                        "fields": {//暂时未用 只是保留让 自己能够知道有这种方式根据不同条件选择不同的搜索分词
                            "keyword_once_pinyin": {//新的分词字段 只分词不存在source productName.keyword_once_pinyin 查询时需要判断如果是单字母使用此搜索
                                "type": "text",
                                "analyzer": "onlyOne_analyzer"
                            }
                        }
                    }
                }
    
            }
    
    
        }
    }

    filter个人理解

    我的理解是   ik分词 然后将分词后的逐项结果通过filter交给拼音分词  雪花啤酒 ik会分成 雪花,啤酒    然后雪花交给pinyin会分词 xue,hua,xh,x,h  啤酒会分词 pi,jiu,p,j

    插入测试数据

    http://127.0.0.1:9200/opcm3/doc/1

    {
        "productName":"雪花纯生勇闯天涯9度100ml"
    }

    put请求:http://127.0.0.1:9200/opcm3/doc/2

    body:

    {
        "productName":"金威纯生勇闯天涯9度100ml"
    }

    查看分词结果

    get请求:http://127.0.0.1:9200/opcm3/topic/{id}/_termvectors?fields=productName

    get请求:http://127.0.0.1:9200/opcm3/topic/{id}/_termvectors?fields=productName.keyword_once_pinyin

    测试搜索

    http://127.0.0.1:9200/opcm3/_search

    {
        "query":{
            "match_phrase":{
                "productName":{
                    "query":"雪花纯生"
                }
            }
        }
    }

    会查出雪花纯生和金威纯生 看个人是模糊匹配还是相邻匹配 选用match或者match_phrase

    我的需求是相邻匹配改为

    {
        "query":{
            "match_phrase":{
                "productName":{
                    "query":"雪花纯生"
                }
            }
        }
    }

    则只会搜索出雪花纯生

    搜索雪花纯生9度的产品

    {
        "query":{
            "match_phrase":{
                "productName":{
                    "query":"雪花纯生9度"
                }
            }
        }
    }

    会发现搜索不出来数据

    原因请查阅:https://www.cnblogs.com/LQBlog/p/10580247.html

    改为就能搜索出来:

    {
        "query":{
            "match_phrase":{
                "productName":{
                    "query":"雪花纯生9度",
                    "slop":5
                }
            }
        }
    }

    pingpin分词还支持很多参数 比如:

     以上模型排查及解决

    添加测试数据

    {
    "productName":"纯生"
    }

    {
    "productName":"纯爽"
    }

    测试

    搜索

    {
        "query":{
            "match_phrase":{
                "productName":{
                    "query":"纯生",
                    "slop":5
                }
            }
        }
    }

    返回结果

    {
        "took": 3,
        "timed_out": false,
        "_shards": {
            "total": 5,
            "successful": 5,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 2,
            "max_score": 2.8277423,
            "hits": [
                {
                    "_index": "opcm3",
                    "_type": "doc",
                    "_id": "1",
                    "_score": 2.8277423,
                    "_source": {
                        "productName": "纯爽"
                    }
                },
                {
                    "_index": "opcm3",
                    "_type": "doc",
                    "_id": "2",
                    "_score": 1.4466299,
                    "_source": {
                        "productName": "纯生"
                    }
                }
            ]
        }
    }

    可以发现纯爽也出来了

    排查

    1.查看纯爽分词结果

    http://127.0.0.1:9200/opcm3/doc/2/_termvectors?fields=productName

    [c,chun,s,sheng]

    [c,chun,s,shuang]

    2.查看搜索分词

    http://127.0.0.1:9200/opcm3/_validate/query?explain
    {
        "query":{
            "match_phrase":{
                "productName":{
                    "query":"纯生",
                    "slop":5
                }
            }
        }
    }

    body

    {
        "valid": true,
        "_shards": {
            "total": 1,
            "successful": 1,
            "failed": 0
        },
        "explanations": [
            {
                "index": "opcm3",
                "valid": true,
                "explanation": "productName:"(c chun) (s sheng)"~5"
            }
        ]
    }

    可以理解为index=(c or chun) and (s or shuang)

    所以c,s 匹配了纯爽

    解决办法

    分词按最小粒度分 搜索 按最大粒度分

    如纯生文档分词为[chun,sheng,chun,sheng,cs,c,s]

    搜索分词为[chun,sheng,chunsheng]

    一下模型就能满足搜索: 雪花,雪花cs ,雪花chunsheng ,xhcs,xh纯生,雪花纯生 都能正确搜索出数据

    {
        "settings": {
            "analysis": {
                "analyzer": {
                    "ik_pinyin_analyzer": {
                        "type": "custom",
                        "tokenizer": "ik_smart",
                        "filter": ["pinyin_max_word_filter"]
                    },
                    "ik_pingying_smark": {
                         "type": "custom",
                         "tokenizer": "ik_smart",
                          "filter": ["pinyin_smark_word_filter"]
                        
                    }
                },
                "filter": {
                    "pinyin_max_word_filter": {
                        "type": "pinyin",
                        "keep_full_pinyin": "true",#分词全拼如雪花 分词xue,hua
                        "keep_separate_first_letter":"true",#分词简写如雪花 分词xh
                        "keep_joined_full_pinyin":true#分词会quanpin 连接 比如雪花分词 xuehua
                    },
                    "pinyin_smark_word_filter": {
                        "type": "pinyin",
                        "keep_separate_first_letter": "false",#不分词简写如雪花 分词不分词xh
                        "keep_first_letter":"false"#不分词单个首字母 如雪花 不分词 x,h
                    }
                }
            }
    
        },
        "mappings": {
            "doc": {
                "properties": {
                    "productName": {
                        "type": "text",
                        "analyzer": "ik_pinyin_analyzer",#做文档所用的分词器
                        "search_analyzer":"ik_pingying_smark"#搜索使用的分词器
                    }
                }
    
            }
    
    
        }
    }

     解决办法2

  • 相关阅读:
    poj-3580-SuperMemo-splay
    JS 添加到事件的多个对象
    1.9 效率高,安排约会
    我展示了视频采集前端vfe和camera,decode等交互驱动的体系结构
    2013年7月27日杂记
    深入JS系列学习4
    深入JS系列学习3
    深入JS系列学习2
    高质量JavaScript代码书写基本要点学习
    给硬件复兴把脉 硬件创新最有机会的十个方向
  • 原文地址:https://www.cnblogs.com/LQBlog/p/10449637.html
Copyright © 2011-2022 走看看