【问题标题】:Elasticsearch 6.8 match_phrase search N-gram tokenizer works not wellElasticsearch 6.8 match_phrase search N-gram tokenizer 效果不佳
【发布时间】:2021-01-24 09:49:29
【问题描述】:

我使用 Elasticsearch N-gram tokenizer 并使用 match_phrase 进行模糊匹配 我的索引和测试数据如下:

DELETE /m8
PUT m8
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "ngram",
          "min_gram": 1,
          "max_gram": 3,
          "custom_token_chars":"_."
        }
      }
    },
    "max_ngram_diff": 10
  },
  "mappings": {
    "table": {
      "properties": {
        "dataSourceId": {
          "type": "long"
        },
        "dataSourceType": {
          "type": "integer"
        },
        "dbName": {
          "type": "text",
          "analyzer": "my_analyzer",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}


PUT /m8/table/1
{
  "dataSourceId":1,
  "dataSourceType":2,
  "dbName":"rm.rf"
}

PUT /m8/table/2
{
  "dataSourceId":1,
  "dataSourceType":2,
  "dbName":"rm_rf"
}
PUT /m8/table/3
{
  "dataSourceId":1,
  "dataSourceType":2,
  "dbName":"rmrf"
}

检查_分析:

POST m8/_analyze
{
  "tokenizer": "my_tokenizer",
  "text": "rm.rf"
}

_分析结果:

{
  "tokens" : [
    {
      "token" : "r",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "rm",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "rm.",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "m",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "m.",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "m.r",
      "start_offset" : 1,
      "end_offset" : 4,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : ".",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : ".r",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : ".rf",
      "start_offset" : 2,
      "end_offset" : 5,
      "type" : "word",
      "position" : 8
    },
    {
      "token" : "r",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "rf",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "f",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "word",
      "position" : 11
    }
  ]
}

当我搜索“rm”时,什么也没找到:

GET /m8/table/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "dbName": "rm"
          }
        }
      ]
    }
  }
}
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
}

但是可以找到'.rf':

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.7260926,
    "hits" : [
      {
        "_index" : "m8",
        "_type" : "table",
        "_id" : "1",
        "_score" : 1.7260926,
        "_source" : {
          "dataSourceId" : 1,
          "dataSourceType" : 2,
          "dbName" : "rm.rf"
        }
      }
    ]
  }
}

我的问题: 为什么连 _analyze 拆分了这些短语都找不到 'rm'?

【问题讨论】:

    标签: elasticsearch tokenize n-gram match-phrase


    【解决方案1】:
    1. my_analyzer 也将在搜索期间使用。

      "mapping":{
       "dbName": {
        "type": "text",
        "analyzer": "my_analyzer" 
        "search_analyzer":"my_analyzer"  // <==== If you don't provide a search analyzer then what you defined in analyzer will be used during search time as well.
      
    2. Match_phrase 查询用于考虑分析文本的位置来匹配短语。例如,搜索“Kal ho”将匹配在分析文本中位置 X 处具有“Kal”和位置 X+1 处具有“ho”的文档。

    3. 当您搜索 'rm' (#1) 时,使用 my_analyzer 分析文本,将其转换为 n-gram 并在该短语的顶部使用_search。因此,结果不是预期的。

    解决方案:

    1. 使用标准分析器和简单的匹配查询

      GET /m8/_search
      {
       "query": {
       "bool": {
         "must": [
           {
             "match": {
               "dbName": {
                 "query": "rm",
                 "analyzer": "standard" // <=========
               }
             }
           }
         ]
       }
       }
       }
      

      在映射期间定义并使用匹配查询(不是 match_phrase)

      "mapping":{
            "dbName": {
             "type": "text",
             "analyzer": "my_analyzer" 
             "search_analyzer":"standard" //<==========
      

    后续问题:为什么要使用带有 n-gram 标记器的 ma​​tch_phrase 查询?

    【讨论】:

    • 我需要模糊匹配一个单词而不是短语,就像单词“abc_def”一样,如果我输入“c_d”,就会找到这个文档。
    • 还有,你知道如何匹配 dat "."在match_phrase?我搜索“rm。”,expexted 一个文档,但所有文档都返回了
    猜你喜欢
    • 2023-01-26
    • 1970-01-01
    • 2018-02-20
    • 2022-09-27
    • 2020-01-15
    • 1970-01-01
    • 2011-06-30
    • 2021-09-22
    • 1970-01-01
    相关资源
    最近更新 更多