Elasticsearch 6.2中没有规范化的完全匹配,不区分大小写的匹配

问题描述 投票:1回答:1

我查看了每篇文章和帖子,我可以找到关于执行完全匹配,不区分大小写的查询,但在实现时,它们不会执行我正在寻找的内容。

在将此问题标记为重复之前,请阅读整篇文章。

给定用户名,我想查询我的Elasticsearch数据库,只返回与用户名完全匹配的文档,但也不区分大小写。

我已经尝试为我的lowercase属性指定username分析器并使用match查询来实现此行为。虽然这解决了不区分大小写匹配的问题,但它在完全匹配时失败。

我研究了使用lowercase规范化器,但这会使我的所有用户名在索引之前都是小写的,所以当我聚合用户名时,它们将以小写形式返回,这不是我想要的。我需要保留用户名中每个字母的原始大小写。

What I want is the following behavior:


Inserting Users

POST {elastic}/users/_doc

{
    "email": "[email protected]",
    "username": "UsErNaMe",
    "password": "1234567"
}

该文档将完全按照它的方式存储在名为users的索引中。

Getting a User by Username

GET {frontend}/user/UsErNaMe

应该回来

{
    "email": "[email protected]",
    "username": "UsErNaMe",
    "password": "1234567"
}

GET {frontend}/user/username

应该回来

{
    "email": "[email protected]",
    "username": "UsErNaMe",
    "password": "1234567"
}

GET {frontend}/user/USERNAME

应该回来

{
    "email": "[email protected]",
    "username": "UsErNaMe",
    "password": "1234567"
}

GET {frontend}/user/UsErNaMe $RaNdoM LeTteRs

不应该退货。

谢谢。

elasticsearch case-insensitive exact-match
1个回答
3
投票

要实现不区分大小写的精确匹配,您需要定义自己的分析器。分析仪需要执行两个操作:

  1. 小写输入值。 (不区分大小写)
  2. 在小写操作之后不对输入进行任何修改。 (用于精确搜索)

以上两点可以通过以下方式实现:

  1. 定义自定义分析器时使用lowercase过滤器。
  2. tokenizer设置为keyword,这将确保在应用小写过滤器后生成输入值的单个标记。

现在,这个自定义分析器可以应用于需要不区分大小写的精确搜索的文本字段。

所以要创建索引,您可以使用以下内容:

PUT test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "case_insensitive_analyzer": {
          "type": "custom",
          "filter": [
            "lowercase"
          ],
          "tokenizer": "keyword"
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "email": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          }
        },
        "username": {
          "type": "text",
          "analyzer": "case_insensitive_analyzer"
        },
        "password": {
          "type": "keyword"
        }
      }
    }
  }
}

在上面case_insensitive_analyzer是必需的分析仪,你可以看到它应用于username领域。

因此,当您将文档索引如下:

PUT test/_doc/1
{
  "email": "[email protected]",
  "username": "UsErNaMe",
  "password": "1234567"
}

对于username领域,输入是UsErNaMe。分析器首先在输入lowercase上应用UsErNaMe滤波器,得到值username。现在在这个值username上它应用keyword标记器,它除了输出在应用过滤器之后获得的值之外什么都不做,作为单个标记,即username

现在,您可以使用以下匹配查询来搜索用户名字段:

GET test/_doc/_search
{
  "query": {
    "match": {
      "username": "USERNAME"
    }
  }
}

使用上面将为您提供所需的输出。将上述查询中的USERNAME替换为usernameUsErNaMeUSERname都将匹配该文档。这样做的原因是,在搜索是否未明确指定分析器时,elasticsearch使用在索引时应用于该字段的分析器。在上面的情况下,当搜索字段username时,case_insensitive_analyzer将应用于输入值,即USERNAME,这将导致令牌username并因此匹配。

© www.soinside.com 2019 - 2024. All rights reserved.