我正在尝试将新项目添加到特定文档中的嵌套对象数组中。 我已经搜索过,似乎部分文档的更新不支持我需要的内容,它用新元素替换了整个数组。 因此,我进行了脚本化更新,该更新通过 REST API 按预期工作:
PUT /transactions
{
"mappings": {
"_doc": {
"properties": {
"userId": { "type": "keyword" },
"transactions": {
"type": "object",
"properties": {
"date": { "type": "date" },
"amount": { "type": "double" }
}
}
}
}
}
}
POST /transactions/_doc/1
{
"userId": "123",
"transactions": [
{ "date": "2019-07-15T10:32:02Z", "amount": 122 },
{ "date": "2019-07-17T22:09:43Z", "amount": 560 }
]
}
POST /transactions/_doc/1/_update
{
"script": {
"source": "ctx._source.transactions.addAll(params.transactions)",
"params": {
"transactions": [
{ "date": "2019-07-14T21:10:22Z", "amount": 890 },
{ "date": "2019-07-15T15:56:18Z", "amount": 54 }
]
}
}
}
然后我将相同的脚本添加到我的 Java 应用程序中,代码如下所示:
List<Transaction> transactions = Collections.singletonList(new Transaction(320));
Script script = new Script(
Script.DEFAULT_SCRIPT_TYPE, Script.DEFAULT_SCRIPT_LANG,
"ctx._source.transactions.addAll(params.transactions);",
Collections.singletonMap("transactions", transactions));
transportClient
.prepareUpdate("transactions", "_doc", 1)
.setFetchSource(false);
.setScript(script);
.get();
当执行上面的代码时,我得到以下远程异常:
Caused by: java.io.IOException: can not write type [class com.example.model.Transaction]
at org.elasticsearch.common.io.stream.StreamOutput.writeGenericValue(StreamOutput.java:713)
at org.elasticsearch.common.io.stream.StreamOutput.lambda$static$9(StreamOutput.java:599)
at org.elasticsearch.common.io.stream.StreamOutput.writeGenericValue(StreamOutput.java:711)
at org.elasticsearch.common.io.stream.StreamOutput.lambda$static$11(StreamOutput.java:621)
at org.elasticsearch.common.io.stream.StreamOutput.writeGenericValue(StreamOutput.java:711)
at org.elasticsearch.common.io.stream.StreamOutput.writeMap(StreamOutput.java:494)
at org.elasticsearch.script.Script.writeTo(Script.java:533)
...
如果我将列表序列化为字符串,则会收到此异常:
org.elasticsearch.common.io.stream.NotSerializableExceptionWrapper: class_cast_exception: Cannot cast java.lang.String to java.util.Collection
最后,我的问题是如何使用 Java API(传输客户端、Elasticsearch 6.3.2)来完成此任务?
一种替代方法是获取整个文档,反序列化它,附加一个新事务,然后更新整个文档,但这似乎太过分了,可能会降低性能。
最佳答案
我只是好奇地查看了 source code从 writeGenericValue
方法来看,ES 似乎不支持任何自定义对象的写入,除了多个 if else 语句中处理的对象(Object[]、List、Map、ReadableInstant、BytesReference)。
从堆栈跟踪来看,script.writeTo
正在尝试将 Transaction
对象写入输出流,但未能成功。将 Transaction
对象转换为单独的 Map,然后发送它可能会解决问题。
关于java - Elasticsearch:将新元素附加到对象的嵌套数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57095782/