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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM