regex - 负前瞻正则表达式在 ES dsl 查询中不起作用
问题描述
我的 Elastic 搜索的映射如下所示:
{
"settings": {
"index": {
"number_of_shards": "5",
"number_of_replicas": "1"
}
},
"mappings": {
"node": {
"properties": {
"field1": {
"type": "keyword"
},
"field2": {
"type": "keyword"
},
"query": {
"properties": {
"regexp": {
"properties": {
"field1": {
"type": "keyword"
},
"field2": {
"type": "keyword"
}
}
}
}
}
}
}
}
}
问题是:
我正在使用 elasticsearch_dsl Q() 形成 ES 查询。当我的查询包含任何复杂的正则表达式时,它在大多数情况下都可以正常工作。但如果它包含正则表达式字符'!',它就完全失败了 在里面。当搜索词包含“!”时,它不会给出任何结果 在里面。
例如:
1.)Q('regexp', field1 = "^[a-z]{3}.b.*")
(完美运行)
2.)Q('regexp', field1 = "^f04.*")
(完美运行)
3.)Q('regexp', field1 = "f00.*")
(完美运行)
4.)Q('regexp', field1 = "f04baz?")
(完美运行)
在以下情况下失败:
5.)Q('regexp', field1 = "f04((?!z).)*")
(失败,没有结果)
我尝试在字段中添加“分析器”:“关键字”以及“类型”:“关键字”,但在这种情况下没有任何效果。
在浏览器中,我尝试检查分析器:关键字在输入失败的情况下将如何工作:
http://localhost:9210/search/_analyze?analyzer=keyword&text=f04((?!z).) *
结果似乎在这里看起来不错:
{
"tokens": [
{
"token": "f04((?!z).)*",
"start_offset": 0,
"end_offset": 12,
"type": "word",
"position": 0
}
]
}
我正在运行如下查询:
search_obj = Search(using = _conn, index = _index, doc_type = _type).query(Q('regexp', field1 = "f04baz?"))
count = search_obj.count()
response = search_obj[0:count].execute()
logger.debug("total nodes(hits):" + " " + str(response.hits.total))
请帮助,这真的是一个烦人的问题,因为所有正则表达式字符在所有查询中都可以正常工作,除了!。
另外,我如何检查我的映射中当前应用了上述设置的分析器?
解决方案
ElasticSearch Lucene 正则表达式引擎不支持任何类型的环视。ES 正则表达式文档相当模棱两可,说匹配一切.*
都非常慢以及使用环视正则表达式(这不仅模棱两可,而且是错误的,因为环顾四周,如果明智地使用,可能会大大加快正则表达式匹配)。
由于您想匹配任何包含f04
和不包含的字符串z
,您实际上可以使用
[^z]*fo4[^z]*
细节
[^z]*
- 除了任何 0+ 字符z
fo4
-fo4
子串[^z]*
- 除 . 之外的任何 0+ 个字符z
。
如果您有一个要“排除”的多字符字符串(例如,z4
而不是z
),您可以使用补码运算符来使用您的方法:
.*f04.*&~(.*z4.*)
这意味着几乎相同但不支持换行符:
.*
- 除换行符以外的任何字符,尽可能多f04
-f04
.*
- 除换行符以外的任何字符,尽可能多&
- 和~(.*z4.*)
- 除了具有的字符串之外的任何字符串z4
推荐阅读
- linux - 在 bash 脚本中执行 `sh -c`
- php - 自定义端点返回空数组
- python - 大 O 复杂性 - 最大范围从第一个循环开始的双循环
- mysql - 将数据库模型从 MySQLWorkbench 导出到 MariaDB PhpMyAdmin
- python - 如何退出这个while循环
- javascript - 使用 async/await 和 Promise 处理错误,n² 种方式让自己在脚下开枪反应原生错误
- sql - 如何从一个脚本调用另一个脚本
- java - 是否可以使用 Java 将打印机添加到 Samba 打印服务器?
- javascript - 如何使事件适用于禁用的字段集中的列表
- tcp - 在 Tcl 中解码二进制数据