当前位置: 首页 > 知识库问答 >
问题:

使用Spring数据在ElasticSearch中使用通用JsonNode存储文档

蔚和安
2023-03-14

我想使用以下实体的Spring Data将未指定的json有效载荷数据存储在Elasticsearch索引中

    @Document(indexName = "message")
    public class Message {
    
        @Id
        private String id;
        private JsonNode payload;

        //getters and setters here
    }

有效负载各不相同,需要以通用的方式存储,也可以轻松地再次加载,这就是为什么我想在这里使用JsonNode。

将写入具有“id”的文档,但字段“payload”为空。

当我在Kibana中查找写入索引的文档时,它如下所示:

_class:
    com.tryout.Message
payload:
id:
    30243006-0844-4438-a7f0-db93518b340f
_id:
    30243006-0844-4438-a7f0-db93518b340f
_type:
    _doc
_index:
    message
_score:
    0 

在索引映射中,“有效负载”也没有创建,它看起来像这样:

{
  "mappings": {
    "_doc": {
      "properties": {
        "_class": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "id": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

有没有办法存储我的通用有效载荷?

(我使用弹性v7.9.2

共有1个答案

乌俊健
2023-03-14

在将spring data elastic search版本升级到4之后,我遇到了这个问题,不幸的是,我没有找到一个明确的答案。阅读spring data elasticsearch文档,我发现:

从4.0版开始,仅使用元对象映射,基于Jackson的映射器不再可用,使用MappingElasticsearchConverter。

经过几天的探索,我终于用这种方式解决了我的问题,我希望它能帮助其他人。

P. s: JsonNode可以包含jsonArray或JsonObject,所以这两种数据类型应该在读/写时处理。

class JsonElasticSearchConverter extends MappingElasticsearchConverter {

    private CustomConversions conversions = new ElasticsearchCustomConversions(Collections.emptyList());

    CustomElasticSearchConverter(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
        super(mappingContext);
        setConversions(conversions);
    }

    CustomElasticSearchConverter(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext, GenericConversionService conversionService) {
        super(mappingContext, conversionService);
        setConversions(conversions);
    }

    @Override
    protected <R> R readValue(@Nullable Object source, ElasticsearchPersistentProperty property,
                              TypeInformation<R> targetType) {

        if (source == null) {
            return null;
        }

        if (targetType.getType() == JsonNode.class) {
            return (R) mapStoredValueToJsonNode(source);
        }

        return super.readValue(source, property, targetType);
    }

    @Override
    protected Object getWriteComplexValue(ElasticsearchPersistentProperty property, TypeInformation<?> typeHint, Object value) {
        if (typeHint.getType() == JsonNode.class) {
            return getWriteJsonNodeValue(value);
        }
        return super.getWriteComplexValue(property, typeHint, value);
    }

    private JsonNode mapStoredValueToJsonNode(Object source) {
        JsonNode jsonNode = null;
        ObjectMapper mapper = new ObjectMapper();
        if (source instanceof ArrayList) {
            ArrayNode array = mapper.valueToTree(source);
            jsonNode = mapper.valueToTree(array);
        }
        if (source instanceof HashMap) {
            jsonNode = mapper.convertValue(source, JsonNode.class);
        }
        return jsonNode;
    }

    private Object getWriteJsonNodeValue(Object value) {
        JsonNode jsonNode = null;
        ObjectMapper mapper = new ObjectMapper();
        if (value instanceof ObjectNode)
            try {
                jsonNode = mapper.readTree(value.toString());
            } catch (IOException shouldNotHappened) {
                //log.warn("This error should not happened" + shouldNotHappened.getMessage());
            }
        else if (value instanceof ArrayNode) {
            ArrayNode array = mapper.valueToTree(value);
            jsonNode = mapper.valueToTree(array);
        }
        return jsonNode;
    }
}
 类似资料:
  • 我想知道是否可以使用Spring数据JPA调用存储过程,它具有resultset和multiple out参数。 我发现了相同https://github.com/spring-projects/spring-data-examples/issues/80的Git问题 如果问题解决了,有人能举一个Spring Boot的例子吗?

  • 我突然想到,可以用三个基于泛型的类来替换每个对象类型的多个类,从而节省大量的样板代码。我不是很清楚该怎么做,事实上这是不是一个好主意?

  • 是否有一种方法可以使通用Spring数据JPA存储库正确处理类似的方法?例如只返回狗,而不返回所有动物?或者至少,最好的变通方法是什么? 它的工作几乎完美,保存每一个动物在自己的桌子上,等等。唯一的问题是:同时返回水豚和狗。这个答案解释说: 这只有在域类使用单表继承时才起作用。我们在引导时能得到的关于domain类的唯一信息是它将是Product对象。因此,对于像findAll()甚至findBy

  • 我正在配置elasticsearch spring应用程序,并遵循我创建的RestHighLevelClient文档: 现在我希望我所有的文档都有snake_case的命名策略,在文档上这是我发现的: 在没有进一步配置的情况下,Spring Data Elasticsearch将使用对象的属性名称作为Elasticsearch中的字段名称。这可以通过使用该属性上的@Field注释来更改单个字段。

  • 我正在使用Spring的RedisTemplate与Redis接口。 目前,我在Redis中存储的数据使用OpsForHash操作,因为这最适合我存储的数据。 这可能使用一个单独的redistemplate吗? 谢了!

  • 我在ES上运行查询,但参数的数量正在增加(由于业务原因)。 根据Spring数据弹性搜索中的文档,您可以使用和有序参数,如,等,用于方法签名中给出的参数,但这种方法似乎有点不舒服 是否可以进行类似于的查询,换句话说,使用SpEL访问参数属性? 而不是以一系列参数的方法结束,比如 更像jpa使用的spring数据 或者是否有其他方法可以在不离开spring数据接口的情况下进行查询?