Elasticsearch受限条件下含连字符词条的查询字符串搜索方案
解决方案:在约束下实现带连字符字符串的查询
问题原因
你的errors.message是text类型,被standard analyzer拆分bop-qa-io-135为bop、qa、io、135四个独立词条,原始通配符查询会按拆分后的词条匹配,导致无法命中包含完整字符串的文档。
可行方案(符合你的约束)
1. 转义双引号实现短语查询
你提到的双引号包裹方法有效,在JSON中需要用反斜杠\转义双引号,让Elasticsearch识别为短语查询(匹配连续的完整字符串)。修改后的查询如下:
GET /test/_search { "query": { "bool": { "must": [ { "query_string": { "query": "\"bop-qa-io-135\"", "default_field": "errors.message", "default_operator": "AND" } }, { "range": {"updated_at": {"gte": "2023-07-03T00:00:00"}}}, { "range": {"updated_at": {"lte": "2023-07-05T00:00:00"}}} ] } }, "from": 0, "size": 300 }
如果需要匹配包含该字符串的任意子串(前后有其他内容),可以将通配符放在短语外:
GET /test/_search { "query": { "bool": { "must": [ { "query_string": { "query": "*\"bop-qa-io-135\"*", "default_field": "errors.message", "default_operator": "AND" } }, { "range": {"updated_at": {"gte": "2023-07-03T00:00:00"}}}, { "range": {"updated_at": {"lte": "2023-07-05T00:00:00"}}} ] } }, "from": 0, "size": 300 }
2. 使用wildcard查询配合keyword子字段(若存在)
如果你的errors.message字段在映射中默认生成了keyword子字段(ES 6.x部分版本会自动生成),可以直接查询该子字段匹配完整字符串:
GET /test/_search { "query": { "bool": { "must": [ { "wildcard": { "errors.message.keyword": "*bop-qa-io-135*" } }, { "range": {"updated_at": {"gte": "2023-07-03T00:00:00"}}}, { "range": {"updated_at": {"lte": "2023-07-05T00:00:00"}}} ] } }, "from": 0, "size": 300 }
若没有该子字段,此方法无效。
3. 脚本查询(性能较低,仅适用于小数据集)
如果以上方法都不行,可使用脚本直接判断字段内容是否包含目标字符串,缺点是会遍历匹配时间范围的所有文档,性能较差:
GET /test/_search { "query": { "bool": { "must": [ { "script": { "script": "doc['errors.message'].value.contains('bop-qa-io-135')" } }, { "range": {"updated_at": {"gte": "2023-07-03T00:00:00"}}}, { "range": {"updated_at": {"lte": "2023-07-05T00:00:00"}}} ] } }, "from": 0, "size": 300 }
为什么你之前加"analyzer": "keyword"无效?
当query_string中使用通配符*时,Elasticsearch会跳过分析器(通配符查询属于模糊匹配,不进行词条拆分),因此analyzer: keyword参数不会生效。
内容的提问来源于stack exchange,提问作者Corel
相关产品推荐
相关产品推荐

