一尘不染

在Elasticsearch上使用负前瞻正则表达式

elasticsearch

我正在尝试对Elasticsearch查询进行否定前瞻,正则表达式为:

(?!.*charge)(?!.*encode)(?!.*relate).*night.*

我要匹配的文本是:

归还了住宿费用,但仍存在建筑问题。喷洒化学药品会引起健康问题,并引起眼睛刺激。

我没有任何幸运。有人可以帮忙吗?

ES查询:

  "query": {
    "filtered": {
      "query": {
        "bool": {
          "must_not": [
            {
              "regexp": {
                "message": {
                  "value": "(?!.*charge)(?!.*encode)(?!.*relate).*night.*",
                  "flags_value": 65535
                }
              }
            }
          ]
        }
      },
      "filter": {
        "match": {
          "resNb": {
            "query": "462031152161",
            "type": "boolean"
          }
        }
      }
    }
  }

阅读 300

收藏
2020-06-22

共1个答案

一尘不染

您可以使用以下两种方法之一来解决此问题:

"value": "~(charge|encode|relate)night~(charge|encode|relate)",

要么

.*night.*&~(.*(charge|encode|relate).*)

带可选的(因为 默认情况下 为ON )

"flags" : "ALL"

它是如何工作的?

在常见的NFA正则表达式中,通常会有负面的环顾四周,以帮助限制更通用的模式(看起来像(?!...)或的样式(?<!...))。但是,在ElasticSearch中,您需要使用特定的
可选运算符

~(波浪号)是 补体 被用于*后它否定的原子权。原子可以是单个符号,也可以是一组内的一组子图案/替代物。

请注意,默认情况下,所有ES模式都锚定在字符串的开头和结尾,您无需在Perl式和.NET以及其他NFA中使用它们,^并且不需要使用它们$

从而,

  • ~(charge|encode|relate)-匹配字符串开头以外的任何文本chargeencode并且relate
  • night -匹配单词 night
  • ~(charge|encode|relate) -匹配除3个子字符串之外的任何文本,直到字符串末尾。

在像Perl这样的NFA正则表达式中,您可以使用经过调节的贪婪令牌来编写该模式:

/^(?:(?!charge|encode|relate).)*night(?:(?!charge|encode|relate).)*$/

第二种模式比较棘手:匹配时,常见的NFA正则表达式通常不会从一个位置跳到另一个位置,因此,通常使用锚定在文本开头的前瞻符号。在这里,使用
INTERSECTION, 我们只能使用2种模式,其中一种将与字符串匹配, 第二种也应与字符串匹配。

  • .*night.*-匹配整个线路(如.匹配任何象征,而是一个换行符,否则,使用(.|\n)*),用night
  • &-
  • ~(.*(charge|encode|relate).*)-不也行chargeencoderelate子在里面。

类似NFA Perl的正则表达式看起来像

/^(?!.*(charge|encode|relate)).*night.*$/
2020-06-22