23 通过ngram分词机制实现index-time搜索推荐

什么是ngram

  假设有个单词quick,5种长度下的ngram

ngram length=1,会被拆成 q u i c k
ngram length=2,会被拆成 qu ui ic ck
ngram length=3,会被拆成 qui uic ick
ngram length=4,会被拆成 quic uick
ngram length=5,会被拆成 quick

  其中任意一个被拆分的部分 就被称为ngram 。

什么是edge ngram

  quick,anchor首字母后进行ngram

q
qu
qui
quic
quick

  上述拆分方式就被称为edge ngram

  使用edge ngram将每个单词都进行进一步的分词切分,用切分后的ngram来实现前缀搜索推荐功能

  举个例子 两个doc
  doc1 hello world
  doc2 hello we

  使用edge ngram拆分

  h
  he
  hel
  hell
  hello -------> 可以匹配 doc1,doc2

  w -------> 可以匹配 doc1,doc2
  wo
  wor
  worl
  world
  e ---------> 可以匹配 doc2

  使用hello w去搜索

  hello --> hello,doc1
  w --> w,doc1

  doc1中hello和w,而且position也匹配,所以,ok,doc1返回,hello world

    ngram和index-time搜索推荐原理

  搜索的时候,不用再根据一个前缀,然后扫描整个倒排索引,而是简单的拿前缀去倒排索引中匹配即可,如果匹配上了,那么就好,就和match query全文检索一样

 

PUT /my_index
{
  "settings":{
    "analysis": {
      "filter":{
        "autocomplete_filter":{
          "type":"edge_ngram",
          "min_gram":1,
          "max_gram":20
        }
      },
      "analyzer": {
        "autocomplete":{
          "type":"custom",
          "tokenizer":"standard",
          "filter":[
            "lowercase",
            "autocomplete_filter"
          ]
        }
      }
    }
  }
}

 

  设置mapping , 查询的时候还是使用standard

PUT /my_index/_mapping
{
  "properties": {
    "title":{
      "type":"text",
      "analyzer": "autocomplete",
      "search_analyzer": "standard"
    }
  }
}

  数据

PUT /my_index/_doc/1
{
  "title":"hello Jack"
}

PUT /my_index/_doc/2
{
  "title":"hello John"
}

PUT /my_index/_doc/3
{
  "title":"hello Jose"
}

PUT /my_index/_doc/4
{
  "title":"hello CAT"
}

     查询

GET /my_index/_search
{
  "query":{
    "match_phrase":{
      "title":"hello J"
    }
  }
}

   响应结果

{
  "took" : 14,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.6750803,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.6750803,
        "_source" : {
          "title" : "hello Jack"
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.6750803,
        "_source" : {
          "title" : "hello John"
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.6750803,
        "_source" : {
          "title" : "hello Jose"
        }
      }
    ]
  }
}

       如果用match,只有hello的也会出来,全文检索,只是分数比较低,推荐使用match_phrase,要求每个term都有,而且position刚好靠着1位,

 

  

 

posted on 2021-08-18 22:57  溪水静幽  阅读(166)  评论(0)    收藏  举报