【问题标题】:Elasticsearch uses wrong Case Folding for Unicode CharactersElasticsearch 对 Unicode 字符使用错误的大小写折叠
【发布时间】:2015-09-08 08:25:04
【问题描述】:

在我的一个项目中,我正在尝试使用 Elasticsearch (1.7) 来查询数据。但是,它会根据 unicode 字符是否大写返回不同的结果。我尝试使用icu_analyzer 来解决问题。

这是一个小例子来演示我的问题。我的索引是这样的,

$ curl -X PUT http://localhost:9200/tr-test -d '
{
  "mappings": {
    "names": {
      "properties": {
        "name": {
          "type": "string"
        }
      }
    }
  },
  "settings": {
    "index": {
      "number_of_shards": "5",
      "number_of_replicas": "1",
      "analysis": {
        "filter": {
          "nfkc_normalizer": {
            "type": "icu_normalizer",
            "name": "nfkc"
          }
        },
        "analyzer": {
          "my_lowercaser": {
            "tokenizer": "icu_tokenizer",
            "filter": [
              "nfkc_normalizer"
            ]
          }
        }
      }
    }
  }
}'

这是一个测试数据来证明我的问题。

$ curl -X POST http://10.22.20.140:9200/tr-test/_bulk -d '
{"index": {"_type":"names", "_index":"tr-test"}}
{"name":"BAHADIR"}'

这是一个类似的查询。如果我使用BAHADIR作为query_string查询,我可以很容易地找到我的测试数据。

$ curl -X POST http://10.22.20.140:9200/tr-test/_search -d '
{
  "query": {
    "filtered": {
      "query": {
        "query_string": {
          "query": "BAHADIR"
        }
      }
    }
  }
}'

在土耳其语中,BAHADIR 的小写版本是 bahadır。在使用bahadır 进行查询时,我期望得到相同的结果。但是 Elasticsearch 找不到我的数据。我无法通过使用 ICU 进行分析来解决这个问题。如果我使用bahadir 查询,它工作得非常好。

我已经阅读了Living in a Unicode WorldUnicode Case Folding。但无法解决我的问题。我仍然无法让 elasticsearch 使用正确的大小写折叠。

更新

我也尝试像这样创建我的索引。

$ curl -X PUT http://localhost:9200/tr-test -d '
{
  "mappings": {
    "names": {
      "properties": {
        "name": {
          "type": "string",
          "analyzer" : "turkish"
        }
      }
    }
  },
  "settings": {
    "index": {
      "number_of_shards": "5",
      "number_of_replicas": "1"
    }
  }
}'

但我得到了相同的结果。如果我使用BAHADIRbahadir 搜索可以找到我的数据,但通过搜索bahadır 无法找到它,这是BAHADIR 的正确小写版本。

【问题讨论】:

    标签: unicode elasticsearch icu


    【解决方案1】:

    您应该尝试在您的设置中使用Turkish Language Analyzer

    {
      "mappings": {
        "names": {
          "properties": {
            "name": {
              "type":     "string",
              "analyzer": "turkish" 
            }
          }
        }
      }
    }
    

    正如您在实现细节中看到的,它还定义了一个turkish_lowercase,所以我想它会为您解决问题。如果您不想要土耳其语分析器的所有其他功能,请定义一个仅包含 turkish_lowercase 的自定义功能

    如果您需要对name字段进行全文搜索,您还应该将查询方法更改为match query,这是单个字段的基本全文搜索方法。

    {
      "query": {
        "match": {
          "name": "bahadır"
        }
      }
    }
    

    另一方面,query string query 更复杂,可以搜索多个字段,允许使用高级语法;它还可以选择传递您要使用的analyzer,因此如果您真的需要这种查询,您应该尝试在查询中传递"analyzer": "turkish"。不过,我不是查询字符串查询的专家。

    【讨论】:

    • 感谢您的快速回复。但我得到了同样的结果。现在,我将尝试您提供的链接中的设置。
    • @bhdrkn 请记住,设置映射后您的文档需要重新索引
    • 为了确定,我正在删除现有索引并使用新映射再次创建。并填充测试数据并再次查询。但什么都没有改变。
    • @bhdrkn 它可以与match query 一起使用吗?
    • 非常感谢!有用!但我不明白为什么?这两个查询有什么区别?你有什么建议的资源来更好地理解 elasticsearch?
    猜你喜欢
    • 1970-01-01
    • 2014-07-08
    • 2013-08-18
    • 2019-07-03
    • 2011-11-21
    • 2022-01-11
    • 2010-10-30
    • 2016-03-29
    • 1970-01-01
    相关资源
    最近更新 更多