Elasticsearch 在不破坏语法的情况下突出显示 HTML 中的匹配项

Elasticsearch highlight matches in HTML without breaking syntax

Elasticsearch 有一个内置的 "highlight" 功能,允许您在结果中标记匹配的术语(比乍听起来更复杂,因为查询语法可以包括近似匹配等)。

我有 HTML 个字段,当我打开突出显示时,Elasticsearch 会在整个 HTML 语法中踩踏。

以这种方式突出显示时,我可以使其 HTML-感知/HTML-安全吗?

我希望突出显示应用于 HTML 文档中的文本,而不是突出显示与搜索匹配的任何 HTML 标记,即搜索 "p" 可能突出显示 <p>p</p> -> <p><mark>p</mark></p>.

我的字段被索引为“type: string”。

documentation says:

Encoder:

An encoder parameter can be used to define how highlighted text will be encoded. It can be either default (no encoding) or html (will escape html, if you use html highlighting tags).

.. 但是 HTML-转义了我已经 HTML-编码的字段,进一步破坏了事情。

这里有两个示例查询

  1. 使用默认编码器:

高亮标签插入其他标签内,即 <p> -> <<tag1>p</tag1>>:

curl -XPOST -H 'Content-type: application/json' "http://localhost:7200/myindex/_search?pretty" -d '
{
  "query": { "match": { "preview_html": "p" } },
  "highlight": {
    "pre_tags" : ["<tag1>"],
    "post_tags" : ["</tag1>"],
    "encoder": "default",
    "fields": {
      "preview_html" : {}
    }
  },
  "from" : 22, "size" : 1
}'

GIVES:
...
      "highlight" : {
        "preview_html" : [ "<<tag1>p</tag1> class=\"text\">TOP STORIES</<tag1>p</tag1>><<tag1>p</tag1> class=\"text\">Middle East</<tag1>p</tag1>><<tag1>p</tag1> class=\"text\">Syria: Developments in Syria are main story in Middle East</<tag1>p</tag1>>" ]
      }

...
  1. 使用 html 编码器:

现有的 HTML 语法被 elasticsearch 转义,这破坏了一些东西,即 <p> -> &lt;<tag1>p</tag1>&gt;:

curl -XPOST -H 'Content-type: application/json' "http://localhost:7200/myindex/_search?pretty" -d '
{
  "query": { "match": { "preview_html": "p" } },
  "highlight": {
    "pre_tags" : ["<tag1>"],
    "post_tags" : ["</tag1>"],
    "encoder": "html",
    "fields": {
      "preview_html" : {}
    }
  },
  "from" : 22, "size" : 1
}'

GIVES:
...
      "highlight" : {
        "preview_html" : [ "&lt;<tag1>p</tag1> class=&quot;text&quot;&gt;TOP STORIES&lt;&#x2F;<tag1>p</tag1>&gt;&lt;<tag1>p</tag1> class=&quot;text&quot;&gt;Middle East&lt;&#x2F;<tag1>p</tag1>&gt;&lt;<tag1>p</tag1> class=&quot;text&quot;&gt;Syria: Developments in Syria are main story in Middle East&lt;&#x2F;<tag1>p</tag1>&gt;" ]
        }
      }

...

实现此目的的一种方法是在分析 preview_html 字段时使用 html_strip char filter
这将确保 while 匹配不会出现在 html 标记上,因此突出显示将忽略它,如下例所示。

示例:

put test
{
   "settings": {
      "index": {
         "analysis": {
            "char_filter": {
               "my_html": {
                  "type": "html_strip"
               }
            },
            "analyzer": {
               "my_html": {
                  "tokenizer": "standard",
                  "char_filter": [
                     "my_html"
                  ],
                  "type": "custom"
               }
            }
         }
      }
   }
}

put test/test/_mapping
{
   "properties": {
      "preview_html": {
         "type": "string",
         "analyzer": "my_html",
         "search_analyzer": "standard"
      }
   }
}

put test/test/1
{
    "preview_html": "<p> p </p>"
}

post test/test/_search
{
   "query": {
      "match": {
         "preview_html": "p"
      }
   },
   "highlight": {
      "fields": {
         "preview_html": {}
      }
   }
}

结果

 "hits": [
         {
            "_index": "test",
            "_type": "test",
            "_id": "1",
            "_score": 0.30685282,
            "_source": {
               "preview_html": "<p> p </p>"
            },
            "highlight": {
               "preview_html": [
                  "<p> <em>p</em> </p>"
               ]
            }
         }
      ]