具有ngram令牌的分析器,取决于期限

时间:2019-06-10 13:45:56

标签: elasticsearch

我正在构建一个分析器,以对术语进行部分搜索。所以我想在索引时间使用2-5 ngram tokenzier,在搜索时使用5-5 ngram。

在索引时间使用2-5个ngram的合理性是长度2的部分项查询应匹配。

在搜索时,如果搜索词的长度小于5,则可以直接在倒排索引中搜索该词。如果len大于5,则该词用5克标记,如果所有标记都匹配,则匹配。

但是,在Elastic中,如果查询词的长度小于5,则使用5-5 ngram tokenziser不会创建任何令牌。 解决方案可能是在搜索时使用2-5令牌生成器,与索引编制相同,但这将导致搜索所有2grams,3grams和4grams令牌,这是没有用的...(5grams令牌就足够了)

这是我当前的索引映射:

{
  "settings" : {
   "analysis":{
        "analyzer":{
           "index_partial":{
              "type":"custom",
              "tokenizer":"2-5_ngram_token"
           },
           "search_partial":{
              "type":"custom",
              "tokenizer": "5-5_ngram_token"
           }
        },
        "tokenizer":{
           "2-5_ngram_token": {
              "type":"nGram",
              "min_gram":"2",
              "max_gram":"5"
           },
           "5-5_ngram_token": {
              "type":"nGram",
              "min_gram":"5",
              "max_gram":"5"
           }
        }
      }
   },
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "name_trans": {
        "type": "text",
        "fields": {
          "partial": {
           "type":"text",
           "analyzer":"index_partial",
           "search_analyzer":"search_partial"
          }
        }
      }
    }
  }
}

所以我的问题是:如果搜索查询的长度小于5,如何创建不执行操作的分析器?如果长度大于5,则创建5克令牌?

----------------------使用解决方案进行更新-------------------- ---

如果len <5且len> = 5则5-5ngram,似乎无法创建不操作的分析器。

围绕执行部分解决方案有两种方法:

1-如@Amit Khandelwal所述,一种解决方案是在索引时间使用max ngram。如果您的字段最多有30个字符,请使用带有ngram 2-30的令牌生成器,并在搜索时搜索准确的字词,而不用ngram分析器对其进行处理(通过字词查询或将搜索分析仪设置为关键字)。 / p>

该解决方案的缺点是,根据最大长度,它可能导致巨大的倒排索引。

2-其他解决方案是创建两个字段:  -一种用于简短搜索查询词的词,可以直接在反向索引中查找,而无需标记  -一个较长的搜索查询词,应标记化 根据搜索查询词的长度,搜索应在这两个字段之一中进行

以下是我用于解决方案2的映射(我选择的短期和长期之间的限制是len = 5):

PUT name_test
{
  "settings" : {
   "max_ngram_diff": 3,
   "analysis":{
        "analyzer":{
           "2-4nGrams":{
              "type":"custom",
              "tokenizer":"2-4_ngram_token",
              "filter": ["lowercase"]
           },
           "5-5nGrams":{
              "type":"custom",
              "tokenizer": "5-5_ngram_token",
              "filter": ["lowercase"]
           }
        },
        "tokenizer":{
           "2-4_ngram_token": {
              "type":"nGram",
              "min_gram":"2",
              "max_gram":"4"
           },
           "5-5_ngram_token": {
              "type":"nGram",
              "min_gram":"5",
              "max_gram":"5"
           }
        }
      }
   },
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "name_trans": {
        "type": "text",
        "fields": {
          "2-4partial": {
           "type":"text",
           "analyzer":"2-4nGrams",
           "search_analyzer":"keyword"
          },
          "5-5partial": {
           "type":"text",
           "analyzer":"5-5nGrams"
          }
        }
      }
    }
  }
}

以及根据搜索词的长度与该映射一起使用的两种请求:

GET name_test/_search
{
  "query": {
    "match": {
      "name_trans.2-4partial": {
        "query": "ema",
        "operator": "and",
        "fuzziness": 0
      }
    }
  }
}

GET name_test/_search
{
  "query": {
    "match": {
      "name_trans.5-5partial": {
        "query": "emanue",
        "operator": "and",
        "fuzziness": 0
      }
    }
  }

也许有一天有帮助的人:)

1 个答案:

答案 0 :(得分:1)

我不确定在Elasticsearch中是否可行,但是我可以建议您一种变通方法,尽管我们的用例有所不同,但我们也可以在我们的应用程序中使用它。

  1. 在要用于部分搜索的字段上使用2-5 ngram tokenzier创建自定义分析器,这会将字段的ngram标记存储在倒排索引中,例如,包含{ {1}}作为值,它将存储foobarfofoofoobfoobaoo,{{1 }},ooboobaoobarobobaobarba

    < / li>
  2. 现在,不是匹配查询,而是对未分析的部分字段使用术语查询,因此您可以阅读这些here的diff b / w。

  3. 因此,在这种情况下,搜索词是否小于5无关紧要,它仍然会与标记匹配,您将获得结果。

现在,让我们在包含bar作为值的字段上进行试运行,并针对某些搜索字词对其进行测试,

情况1:如果搜索词包含少于5个字符,例如arfoobarfoooarbarooboba,但它们仍会匹配,因为这些标记存在于倒排索引中。

情况2:搜索词包含等于或大于5个字符,例如barooba,然后它还返回文档,因为索引包含这些标记。

请让我知道是否清楚,或者您需要其他说明。