几天前我开始使用Elasticsearch,我创建了一些分析器和Map,并成功地在其中插入了一些数据。当我试图查询包含一些特殊字符的数据时,问题发生了。最初我使用standard
分析器,但在阅读了更多选项后,我决定使用whitespace
,因为它也可以标记特殊字符。然而,我仍然无法查询数据。但是,如果我输入field.raw
(其中field是对象的实际属性),我会得到我需要的结果。但是,.raw
绕过了分析器,我想知道它是否会破坏它的目的。由于空格对我不起作用,我恢复到了standard
。
这是我构建的分析器:
PUT demoindex
{
"settings": {
"analysis": {
"filter": {
"ngram": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20,
"token_chars": [
"letter",
"digit"
]
},
"splcharfilter": {
"type": "pattern_capture",
"preserve_original": true,
"patterns": [
"([?/-])"
]
}
},
"analyzer": {
"my_field_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"ngram",
"splcharfilter"
]
}
}
}
}
}
我构建的Map:
PUT demoindex/_mapping
{
"properties": {
"name": {
"type": "text",
"analyzer": "my_field_analyzer",
"search_analyzer": "simple",
"fields": {
"raw": {
"type": "keyword"
}
}
},
"area": {
"type": "text",
"analyzer": "my_field_analyzer",
"search_analyzer": "simple",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
不起作用的查询:
GET /demoindex/_search?pretty
{
"from": 0,
"query": {
"bool": {
"filter": [
{
"term": {
"area": {
"value": "is - application"
}
}
},
{
"term": {
"name": {
"value": "hem"
}
}
}
]
}
},
"size": 15
}
有效的质询:
GET /demoindex/_search?pretty
{
"from": 0,
"query": {
"bool": {
"filter": [
{
"term": {
"area.raw": {
"value": "is - application"
}
}
},
{
"term": {
"name": {
"value": "hem"
}
}
}
]
}
},
"size": 15
}
正如您所注意到的,我不得不使用area.raw
来匹配内容并返回文档。由于name不应包含任何特殊字符,因此没有.raw
应该是可以的,但其他字段将包含特殊字符,这些字符可能不限于-
。
那么,有人能指出我做错了什么,或者我理解错了什么吗?或者有没有更好的方法来实现这一点?
P.S:版本信息
ElasticSearch:7.10.1
Lucene版本:8.7.0
1条答案
按热度按时间hgb9j2n61#
1.不分析关键字字段。
1.文本字段进行分析。
要检查这些是如何分析的,以及生成了哪些令牌,可以使用Elasticsearch中的“Analyze API”。
在您的情况下:
它会输出
因此,当您提供值area.raw:“is - application”作为其关键字类型时,它将按原样保存,因此您的下面的术语查询有效。
术语查询用于精确匹配,应与未分析的字段一起使用,如area.raw,在您的情况下它是关键字。
但是,当您对文本字段应用相同的Term查询时,它并不工作,因为它试图完全匹配所提供的值,但正如我们在上面看到的,区域值已被标记化,
因此,正如Elasticsearch建议的那样,最好使用“匹配”查询来查找文本(分析字段)。