首页 > 解决方案 > 使用带有 Ngram 过滤器的精确前缀/匹配短语前缀查询

问题描述

我的目标是搜索长度为一两个字符的查询文本。这是我对索引的设置。

"settings" : {
      "index" : {
        "number_of_shards" : "5",
        "provided_name" : "my_user",
        "analysis" : {
          "filter" : {
            "ngrammed" : {
              "type" : "ngram",
              "min_gram" : "3",
              "max_gram" : "50"
            }
          },
          "analyzer" : {
            "ngrammed_ci" : {
              "filter" : [
                "lowercase",
                "ngrammed"
              ],
              "type" : "custom",
              "tokenizer" : "standard"
            },
            "keyword_ci" : {
              "filter" : [
                "lowercase"
              ],
              "type" : "custom",
              "tokenizer" : "keyword"
            }
          }
        }
      }
    }

我有一组具有以下分析器的显示名称字段的用户。假设我有几个用户的名称像 Allen, Alec, Kimball,Polly 我面临的问题是,当我使用 2 个字符长度的查询字符串(如& )进行搜索al时,它也匹配,因为 ngram 过滤器标记为倒置指数。我试图避免这种情况。还想知道是否有任何方法可以在不更改索引方面的任何内容的情况下实现此功能,并且仅针对查询方面进行更改。AllenAlecKimballKimballall

"user_display_name" : {
  "type" : "text",
  "fields" : {
    "ci" : {
    "type" : "text",
    "analyzer" : "keyword_ci"
    }
  "cs" : {
    "type" : "keyword"
    }
  },
  "analyzer" : "ngrammed_ci",
  "search_analyzer" : "standard"
}

标签: elasticsearchsearchn-gram

解决方案


正如您所提到的,您想要一个不需要更改索引的解决方案,我建议您使用前缀查询,但在发送前缀查询之前 ,请确保您将搜索词小写,如我所见,您使用 keyword_ci了 which将索引中的用户名小写,以提供不区分大小写的搜索。

让我向您展示一个关于您的示例数据的工作示例

我在最低要求的映射下创建

{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "keyword_ci": {
            "filter": [
              "lowercase"
            ],
            "type": "custom",
            "tokenizer": "keyword"
          }
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "user_display_name": {
        "type": "text",
        "analyzer": "keyword_ci"
      }
    }
  }
}

索引您的四个用户

{
  "user_display_name" : "Polly"
}

搜索查询,请注意前缀查询不是小写的,因此您需要在应用程序中进行小写,然后才能使用以下前缀查询

{
  "query": {
    "prefix" : { "user_display_name" : "al" }
  }
}

以下是您的预期结果

 "hits": [
      {
        "_index": "internaledgepre",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.0,
        "_source": {
          "user_display_name": "Allen"
        }
      },
      {
        "_index": "internaledgepre",
        "_type": "_doc",
        "_id": "2",
        "_score": 1.0,
        "_source": {
          "user_display_name": "Alec"
        }
      }
    ]

此外,我还写了一篇关于各种部分搜索技术的博客文章我的这个 SO 答案讨论了如何根据各种因素选择部分搜索方法。请仔细阅读它们以深入了解。


推荐阅读