如何利用Elasticsearch中存储的正则属性匹配指定字符串?
用Elasticsearch中存储的正则表达式匹配目标字符串
嘿,我完全懂你的需求——你把带正则格式的HTTP路由存在Elasticsearch里,现在想要反过来,用这些存储在字段里的正则去匹配给定的目标字符串,而不是Elasticsearch常规的「用正则匹配字段值」的逻辑,对吧?
可惜Elasticsearch并没有原生提供你伪代码里的regexp_property这种查询类型,但我们可以用Painless脚本查询来实现这个需求,这是最直接的方案。
方法一:直接使用脚本过滤查询
你可以通过script查询来编写逻辑:编译字段中的正则表达式,然后用目标字符串去匹配它。具体的查询示例如下:
{ "query": { "bool": { "filter": { "script": { "script": { "source": "// 先检查字段是否有值,避免空指针异常\nif (doc['route_settings.regex'].size() == 0) { return false; }\n// 编译字段中的正则表达式\nPattern pattern = Pattern.compile(doc['route_settings.regex'].value);\n// 用目标字符串执行匹配\nMatcher matcher = pattern.matcher(params.subject);\nreturn matcher.matches();", "params": { "subject": "/news/123/detail.html" // 这里替换成你的目标字符串 }, "lang": "painless" } } } } } }
关键注意事项:
- 正则语法兼容:Painless使用Java的正则表达式语法,所以你存储的路由正则需要符合Java规则,比如原来的
/news/(d+)/.+.html要修正为/news/(\\d+)/.+\\.html(注意转义特殊字符)。 - 性能考量:脚本查询会对每个匹配的文档编译正则表达式,如果你的数据量很大,可能会有性能损耗。如果这类查询很频繁,可以考虑提前做一些优化(比如缓存常用正则,或者用runtime字段预计算)。
- 权限配置:确保你的Elasticsearch集群允许Painless使用正则相关方法,需要在
elasticsearch.yml中设置:script.painless.regex.enabled: true,否则会报错。
方法二:用Runtime Field简化重复查询
如果这类匹配查询是高频操作,你可以定义一个Runtime Field,把匹配逻辑封装进去,后续查询会更简洁:
首先,你可以在索引的映射中添加这个Runtime Field(或者在查询时动态定义):
{ "mappings": { "runtime": { "matches_target": { "type": "boolean", "script": { "source": "if (doc['route_settings.regex'].size() == 0) { return false; }\nPattern pattern = Pattern.compile(doc['route_settings.regex'].value);\nreturn pattern.matcher(params.subject).matches();", "params": { "subject": "" // 可以设置默认值,查询时覆盖 } } } } } }
之后查询时,只需要传递目标字符串参数,然后匹配这个布尔字段即可:
{ "query": { "term": { "matches_target": true } }, "params": { "subject": "/news/456/article.html" // 传递你的目标字符串 } }
这种方式的好处是把匹配逻辑和查询逻辑分离,多次查询时不需要重复写脚本。
内容的提问来源于stack exchange,提问作者Dygnus
相关产品推荐
相关产品推荐

