【问题标题】:Elasticsearch multiple analyzers for a single field单个字段的 Elasticsearch 多个分析器
【发布时间】:2015-09-05 17:35:24
【问题描述】:

我将不同类型的文档存储在具有严格预定义映射的单个索引中。它们都有一些字段(比如“body”),但我希望在索引时对它们进行稍微不同的分析(例如,对特定文档使用不同的标记过滤器)并在搜索时以相同的方式处理。据我所知,不能为每个文档指定分析器。

我也考虑过使用:

  1. 对象字段具有针对文档类型的不同分析子字段,因此每个文档只有一个填充的子字段(例如,“body.mail”、“body.html”)。问题是我无法搜索整个“正文”字段,该字段将查看其所有子字段(以免破坏现有应用程序)。
  2. 多字段的新转世(在“正文”字段中使用通用分析器并在其中自定义分析“邮件”、“html”等)。但是,我不确定是否可以在索引时直接使用它们,而在搜索时间接使用它们(例如,用{"mail":"smth"} 保存对象以使用特定的索引分析器,然后通过"query":{"body":"smth"} 搜索以使用通用搜索分析器)。
  3. 要将“正文”分成具有不同映射的多个字段,请将它们从_all 中删除,并将copy_to 设置为单个body 字段。我不确定,但由于复制,它会增加大量索引开销。

【问题讨论】:

  • 为什么不索引“mail”、“html”等不同的字段,为每个字段设置不同的分析器,并使用多重匹配查询来搜索所有这些字段? elastic.co/guide/en/elasticsearch/reference/current/…
  • 在我看来,这两个要求不可能同时出现:search on the whole "body" field which would look through all its subfields (**to not break the existing application**)analyzed slightly differently when indexed and treaten the same way while searched。必须付出一些。
  • @Ita Legacy 原因。该字段上已经有很多搜索查询,因此用多重匹配替换每个查询会很困难且容易出现样板。
  • "copy_to to a single body field" 将使用 body 字段的分析器,因此,即使您在内部有 copy_to 的字段上有不同的分析器body 您将获得由 body 字段分析器分析的文本。

标签: indexing elasticsearch


【解决方案1】:

正如我在 cmets 中提到的,您想要的都是不可能的。一句话,您的要求是:以多种方式分析相同的数据,但作为单个字段进行搜索,因为这会破坏现有的应用程序。

             -- body.html          
             -- body.email
body field ---- body.content     --- all searched as "body"
            ...
             -- body.destination
             -- body.whatever
  • 您的第一个选项是 multi-fields,它具有这个确切目的:以多种方式分析相同的数据。问题是您无法搜索"body" 并期望ES 搜索body.htmlbody.email... 即使这可能,您也希望使用不同的分析器进行搜索。再次,不可能。此选项要求您更改应用程序并在multi_matchquery_string 中搜索每个字段。

  • 您的第二个选项 - reincarnation of multi-fields - 将再次不起作用,因为 您不能在后台引用 body 和 ES,以匹配 mailcontent 等.

  • 第三个选项 - 使用 copy_to - 将不起作用,因为复制到另一个字段“X”意味着索引正在复制的数据将使用 X 的分析器进行分析,并且这打破了您对相同数据进行不同分析的要求。

  • 可能还有第四个选项 - "path": "just_name" from multi_fields - 乍一看它应该可以工作。这意味着,您可以拥有 3 个多字段(电子邮件、内容、html),这三个字段都有一个 body 子字段。拥有"path": "just_name" 允许您仅搜索body,即使body 是多个其他字段的子字段。但这是不可能的,因为这种类型的多字段不会接受同一body的不同分析器

无论哪种方式,您都需要更改您的要求中的某些内容,因为它们不会按照您想要的方式工作。


话虽如此,我很想知道您在应用程序中使用了哪些查询。从查询body 字段到在multi_match 中查询body.*,这将是一个简单的更改(是的,您需要更改您的应用)。

我还有另一种解决方案:创建多个索引,为body 的每个分析器创建一个索引。例如,对于 mailcontenthtml,您定义了三个索引:

PUT /multi_fields1
{
  "mappings": {
    "test": {
      "properties": {
        "body": {
          "type": "string",
          "index_analyzer": "whitespace",
          "search_analyzer": "standard"
        }
      }
    }
  }
}
PUT /multi_fields2
{
  "mappings": {
    "test": {
      "properties": {
        "body": {
          "type": "string",
          "index_analyzer": "standard",
          "search_analyzer": "standard"
        }
      }
    }
  }
}
PUT /multi_fields3
{
  "mappings": {
    "test": {
      "properties": {
        "body": {
          "type": "string",
          "index_analyzer": "keyword",
          "search_analyzer": "standard"
        }
      }
    }
  }
}

您会看到它们都具有相同的 type 和相同的字段名称 - body - 但不同的 index_analyzers。然后定义一个别名:

POST _aliases
{
  "actions": [
    {"add": {
        "index": "multi_fields1",
        "alias": "multi"}},
    {"add": {
        "index": "multi_fields2",
        "alias": "multi"}},
    {"add": {
        "index": "multi_fields3",
        "alias": "multi"}}
  ]
}

将别名命名为与当前索引相同。应用程序不需要更改,它将使用相同的名称进行索引搜索,此名称不会指向索引,而是指向别名,该别名又引用您的多个索引。需要改变的是你如何索引文档,因为html 文档需要进入multi_fields1 索引,email 文档需要在multi_fields2 索引中索引等等。

无论您找到/选择什么解决方案,您的需求都需要改变,因为您想要的方式是不可能的。

【讨论】:

    【解决方案2】:

    我认为您可以使用多字段。使用多字段,您可以为每个子字段定义分析器(索引和搜索),并根据应用程序需求对相应字段进行搜索。 一般情况下,索引分析器可能因字段而异,搜索分析器也是如此。

    { “你的类型”:{ “特性”:{ “身体” : { “类型”:“字符串”, “索引”:“已分析”, “index_analyzer”:“index_body_analyzer”, "search_analyzer" : "search_body_analyzer", “字段”:{ “邮件” : { “类型”:“字符串”, “索引”:“已分析”, “index_analyzer”:“index_bodymail_analyzer”, “search_analyzer”:“search_bodymail_analyzer” }, “html”:{ “类型”:“字符串”, “索引”:“已分析”, “index_analyzer”:“index_bodyhtml_analyzer”, “search_analyzer”:“search_bodyhtml_analyzer” } } } } }

    【讨论】:

    • 是否可以将数据“放入”html 字段(及其 index_analyzer),然后在 body 字段(及其 search_analyzer)上进行搜索?后者对于向后兼容至关重要。
    • 您的意思是将差异数据索引到html ?或与body 相同的数据,只是 index_analyzer 的区别?如果数据相同,那么 ES 已经通过多字段定义为您完成了。您可以提供有关问题的示例数据以使事情变得清晰。
    • 我的意思是像[{"id":1,"html":"..."},{"id":2,"mail":"..."}](或"body.html":"..."等)这样索引对象以使用不同的索引分析器,但像"query":"body:smth"这样的搜索使用单个搜索分析器。我目前正在试验映射,但仍然无法使我的旧搜索界面(在查询中使用 body)工作。
    • 这种情况下我们需要更改查询来跨字段搜索,否则我认为不可能。另一个部分解决方案是在应用程序级别(在索引之前)预处理文档,或者自己编写一个可以在索引时“if-else”的分析器。
    猜你喜欢
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多