Elasticsearch 对 Unicode 字符使用了错误的大小写折叠
Elasticsearch uses wrong Case Folding for Unicode Characters
在我的一个项目中,我尝试使用 Elasticsearch (1.7) 来查询数据。但是,它 returns 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 World and Unicode 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"
}
}
}'
但我得到了相同的结果。如果我使用 BAHADIR
或 bahadir
搜索可以找到我的数据,但无法通过搜索 bahadır
找到它,这是 BAHADIR
的正确小写版本。
您应该尝试在您的设置中使用 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"
。不过我不是查询字符串查询的专家。
在我的一个项目中,我尝试使用 Elasticsearch (1.7) 来查询数据。但是,它 returns 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 World and Unicode 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"
}
}
}'
但我得到了相同的结果。如果我使用 BAHADIR
或 bahadir
搜索可以找到我的数据,但无法通过搜索 bahadır
找到它,这是 BAHADIR
的正确小写版本。
您应该尝试在您的设置中使用 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"
。不过我不是查询字符串查询的专家。