Elasticsearch -如果字段具有相同的名称但有多个Map该怎么办

os8fio9y  于 2022-11-02  发布在  ElasticSearch
关注(0)|答案(2)|浏览(218)

我使用Elasticsearch来存储从我的系统之外的多个源发送的数据,也就是说,我不控制传入的数据--我只是接收json文档并存储它。我没有在中间使用过滤器的logstash,只有ES和Kibana。每个数据源都发送自己的数据类型,并且它们都存储在同一个索引中但是由于我无法控制发送给我的数据,因此可以接收字段具有相同名称和不同结构的不同类型的文档。

例如,假设我有type 1和type 2,字段为FLD,在这两种情况下都是对象,但该对象的结构不同。具体地说,FLD.name在type 1中是字符串字段,而在type 2中是对象。在这种情况下,当type 1数据到达时,它被成功存储,但当type 2数据到达时,它被拒绝:

无法在索引myindex、类型[type 2]上放置Map
异常错误:[FLD]的Map器与其他类型中的现有Map冲突[无法将非对象Map[FLD.name]与对象Map[FLD.name]合并]
ES文档明确声明,不同Map类型中同一索引中具有相同名称的字段在内部Map到同一字段,并且必须具有相同的Map(请参阅此处)。

我的问题是在这种情况下我能做些什么?我更喜欢将所有类型保存在同一个索引中。有没有可能为字段名添加一个每种类型唯一的后缀或类似的东西?还有其他解决方案吗?我是一个Elasticsearch新手,所以可能我错过了一些简单的东西...提前感谢。

apeeds0o

apeeds0o1#

如果在索引之前不进行预处理,就无法对任意JSON进行索引--即使Dynamic templates也不够灵活。
您可以将嵌套对象扁平化为键-值对,并使用Nested datatypeMulti-fieldsignore_malformed来索引任意JSON(即使存在类型冲突),如here所述。不幸的是,如果您试图将字符串与kv_pairs.value.long匹配,Elasticsearch仍然会在查询时抛出异常,因此您必须根据值的格式选择适当的字段。

qlzsbp2j

qlzsbp2j2#

我认为这不是最佳实践,但您可以将字段内容存储为String,并在检索信息后手动进行反序列化。
所以,想象一下这样一个类:

class Person {
    private final Object name;
}

它可以接收StringList或任何其他Object的List,仅举个例子
因此,您可以将Person序列化为String并保存它,而不是序列化为String将内容保存在另一个类上,例如:

String personContent new ObjectMapper().writeValueAsString(person);
RequestDto dto = new RequestDto(personContent);
String dtoContent new ObjectMapper().writeValueAsString(dto);

并保存dtoContent

IndexRequest request = new IndexRequest("persons")
request.source(dtoContent, XContentType.JSON);
IndexResponse response = client.index(request, RequestOptions.DEFAULT);

RequestDto将是一个具有String字段的简单类:

class RequestDto {
    private String content;
}

我不是ElasticSearch的Maven,但是通过验证,你可能会失去很多ElasticSearch的特性。

相关问题