elasticsearch 上的负前瞻正则表达式

negative lookahead regex on elasticsearch

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

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

我匹配的文本是:

credited back on night stay, still having issues with construction. causing health issues due to a chemical being sprayed and causes eyes to irritated.

我运气不好。有人可以帮忙吗?

ES 查询:

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

您没有使用 锚点 进行前瞻。尝试在模式的开头使用“^”,它应该可以工作。

解决方案

您可以通过以下两种方式解决问题:

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

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

有一个可选的(因为它是开启的默认

"flags" : "ALL"

它是如何工作的?

在常见的 NFA 正则表达式中,您通常会使用否定环视来帮助限制更通用的模式(那些看起来像 (?!...)(?<!...) 的模式)。但是,在 ElasticSearch 中,您需要使用特定的 optional operators.

~(代字号)是 补码,*用于否定紧随其后的原子。原子可以是单个符号,也可以是一组 subpatterns/alternatives 中的一组。

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

因此,

  • ~(charge|encode|relate) - 从字符串开头匹配除 chargeencoderelate
  • 之外的任何文本
  • 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.*$/