【问题标题】:Elastic Search filtered aliases with unmapped fields具有未映射字段的 Elastic Search 过滤别名
【发布时间】:2015-03-11 02:34:31
【问题描述】:

我最近开始在 Elastic Search (documentation here) 中使用 filtered aliases,但有些用例我不知道如何处理。

用例

我在 ElasticSearch 中为事实编制索引的每个文档都有一个名为“tenantId”的字段(还有一些其他字段,例如“type”、“id”等)。现在所有文档都驻留在同一个索引中,所以每个租户我想确保我创建了一个过滤的别名。现在,我想在创建租户本身并方便使用“tenantId”后立即创建过滤别名。

问题

当我尝试使用他们的 java 客户端以编程方式创建别名时,出现以下异常:

Caused by: org.elasticsearch.index.query.QueryParsingException: 
     [mdm-master] Strict field resolution and no field mapping 
     can be found for the field with name [tenantId] 

研究更多,我发现我可能可以使用动态模板来实现这一点。所以我创建了一个模板,将其保存在config/templates 下,重新创建了我的索引并再次尝试了同样的事情。再次遇到同样的异常。在阅读文档更多here(页面底部3行)时,我发现即使我尝试将以下属性index.query.parse.allow_unmapped_fields更改为true(我还没有尝试过),对于过滤的别名,它会强制它为假。

现在的问题是,我该如何处理我的用例?我不知道相应类型的映射,但我所知道的事实是,我索引的每个文档,无论类型如何,总是有一个名为 tenantId 的字段,这就是我想要创建过滤别名的内容.

编辑

我发现了几个有用的链接。不确定这是固定在哪个版本上。 filtered aliases in templates do not inherit mappings from aliased index #8473 index.query.parse.allow_unmapped_fields setting does not seem to allow unmapped fields in alias filters #8431

第二次编辑

为 ElasticSearch 找到了一个开放的错误,具有完全相同的问题。等待 ES 开发人员回复。 Failure to create Filtered Alias on empty index with template mappings #10038

非常感谢所有帮助!几天以来我一直在尝试解决这个问题,但没有运气:(。

以下是我用来添加过滤别名的代码,以及默认的映射json模板

模板

{
  "template-1": {
    "template": "*",
    "mappings": {
      "_default_": {
        "properties": {
          "type": {
            "type": "string",
            "index": "not_analyzed"
          },
          "id": {
            "type": "string",
            "index": "not_analyzed"
          },
          "tenantId": {
            "type": "string",
            "index": "not_analyzed"
          }
        }
      }
    }
  }
}

JAVA 客户端

(你现在可以忽略“Observable”相关的东西)

public Observable<Boolean> createAlias(String tenantId) {

        FilterBuilder filter = FilterBuilders.termFilter("tenantId", tenantId);
        ListenableActionFuture<IndicesAliasesResponse> response = client.admin().indices().prepareAliases().addAlias("mdm-master", tenantId, filter).execute();
        return Observable.from(response)
                .map((IndicesAliasesResponse apiResponse) -> {
                    return apiResponse.isAcknowledged();
                });
    }

【问题讨论】:

    标签: java elasticsearch elasticsearch-mapping


    【解决方案1】:

    我是在 ES Github Failure to create Filtered Alias on empty index with template mappings #10038 上发布最新一期的人。我目前发现的最快的解决方法(降级到 1.3 除外,其中不存在此问题)是在创建别名之前使用该字段为文档编制索引。

    如果你有一个多租户的索引,你应该只需要在创建索引的时候为一个包含必填字段的文档建立一次索引,然后你就可以创建别名了。

    如果您尝试我在 GitHub 问题中发布的复制案例,但在创建别名之前,请运行以下命令:

    curl -XPOST  'http://localhost:9200/repro/dummytype/1' -d '{
       "testfield": "dummyvalue"
    }'
    

    那么您应该能够在字段testfield 上添加过滤别名。

    编辑 - 回复第一条评论: 我认为在模板中使用映射是一种疏忽。创建索引时,会将模板应用于匹配索引。我认为这里的问题是模板的通用映射部分在获得文档索引之前实际上应用。 如果您将问题中的模板更改为以下内容,则可以观察到此行为:

    curl -XPUT 'http://localhost:9200/_template/repro' -d '{
      "template": "repro",
      "settings": {
        "index.number_of_shards": 1,
        "index.number_of_replicas": 0
      },
      "mappings": {
        "dummytype": {
          "properties": {
            "testfield": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        }
      }
    }'
    

    然后您就可以创建索引并添加过滤后的别名,而无需为任何文档编制索引。

    正如我所说,我认为这是 ES 模板应用程序中的一个错误。

    【讨论】:

    • 是的。我实际上尝试过它并且它对我有用,尽管我仍然不明白为什么我必须提供具有特定类型的映射。从设计的角度来看,过滤的别名不应该与“类型”本身做任何事情,而只需要映射特定字段,并且客户端有责任确保所有索引文档中都存在该字段(如果这就是他们的用例)。 ES 不应该为客户做出这个决定,而是一些更可配置的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-15
    • 2021-04-03
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    • 2016-02-05
    • 2018-01-02
    相关资源
    最近更新 更多