在使用elasticsearch 7时,我尝试使用simple query string query来搜索不同的字段,包括text
和keyword
。下面是一个最小的、可重现的示例,以显示初始设置和问题:
mapping.json:
{
"dynamic": false,
"properties": {
"publicId": {
"type": "keyword"
},
"eventDate": {
"type": "date",
"format": "yyyy-MM-dd",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"name": {
"type": "text"
}
}
}
test-data1.json:
{
"publicId": "a1b2c3",
"eventDate": "2022-06-10",
"name": "Research & Development"
}
test-data2.json
{
"publicId": "d4e5f6",
"eventDate": "2021-05-11",
"name": "F.inance"
}
在本地主机19200上运行的ES上创建索引:
#!/bin/bash -e
host=${1-localhost:19200}
dir=$( dirname `readlink -f $0` )
mapping=$(<${dir}/mapping.json);
param="{ \"mappings\": $mapping}"
curl -XPUT "http://${host}/test/" -H 'Content-Type: application/json' -d "$param"
curl -XPOST "http://${host}/test/_doc/a1b2c3" -H 'Content-Type: application/json' -d @${dir}/test-data1.json
curl -XPOST "http://${host}/test/_doc/d4e5f6" -H 'Content-Type: application/json' -d @${dir}/test-data2.json
现在的任务是支持像"研发","研发2022 - 06 - 10","金融"(注意删除的点)或简单的"a1b2c3"这样的搜索。例如,使用这样的查询:
{
"from": 0,
"size": 20,
"query": {
"bool": {
"must": [
{
"simple_query_string": {
"query": "Research & Development 2022-06-10",
"fields": [
"publicId^1.0",
"eventDate.keyword^1.0",
"name^1.0"
],
"flags": -1,
"default_operator": "and",
"analyze_wildcard": false,
"auto_generate_synonyms_phrase_query": true,
"fuzzy_prefix_length": 0,
"fuzzy_max_expansions": 50,
"fuzzy_transpositions": true,
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"version": true
}
这种设置的问题在于,文本字段的standard analyzer删除了大部分标点符号,当然也删除了"与"字符。简单的查询字符串查询将查询拆分为三个标记[research, &, development]
,并使用and
运算符搜索所有字段。("Research"和"Development"),但在任何字段中都没有与"and"匹配的项。因此结果为空。
现在,我想到了一个解决方案:使用另一个分析器whitespace analyzer为name
添加第二个字段,该分析器不会删除标点符号:
{
"dynamic": false,
"properties": {
"publicId": {
"type": "keyword"
},
"eventDate": {
"type": "date",
"format": "yyyy-MM-dd",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"name": {
"type": "text",
"fields": {
"whitespace": {
"type": "text",
"analyzer": "whitespace"
}
}
}
}
}
这样,所有搜索都可以正常工作,包括与name
字段的"F. inance"匹配的"Finance"。此外,"Research & Development"与name
字段和name.whitespace
匹配,但最关键的是&
与name.whitespace
匹配,因此返回结果。
我现在的问题是:给定实际设置包括更多字段和大量数据的事实,添加附加字段并因此以相同方式索引大多数项两次似乎相当繁重。是否有办法仅将与标准分析器的项name
不同的被分析项索引到name.whitespace
,即不在"父"字段中?例如,"研发"导致name
的术语[research, development]
和name.whitespace
的术语[research, development, &]
-理想地,它将仅索引[&]
以得到name.whitespace
。
或者有没有一个更优雅/性能更好的解决方案来解决这个特定的问题?
1条答案
按热度按时间ewm0tg9j1#
我想你可以为所有的字符串字段定义一个动态属性Map,并使用空白分析器,因为你的用例有搜索非标准标记的规范,另外,你可以在Map中指定那些你不需要空白标记器的字段。
这将确保使用标准标记器分析已经Map的字段,而使用空白分析其他字段(动态或未Map字段),从而减少复杂性、字段重复等。