- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我遇到了this question and answer,展示了如何将数据从DynamoDB推送到Elasticsearch进行全文本搜索索引。但是,我们的应用程序未使用Lambda。相反,我们使用Apache Camel捕获DynamoDB Streams事件,并希望从那里将记录推送到Elasticsearch。
由于我们使用的是AWS开发工具包v2,因此我们不会捕获包含DynamoDB记录的DynamodbEvent
类或对应的DynamodbStreamRecord
记录类。相反,我们正在接收software.amazon.awssdk.services.dynamodb.model.Record
对象。鉴于此,我们如何在Elasticsearch中序列化该数据并随后对其进行索引?在引用的另一个问题中,记录被转换为JSON字符串,然后发送给Elasticsearch。 v2 Record
类有办法做到这一点吗?答案中提到的ItemUtils
类不再存在,因此我不知道另一种序列化它的方法。
您能提供的任何帮助将不胜感激!
最佳答案
与您提供的示例类似,您可以尝试以下操作:
public void processRecord(Record record, String index, String type, RestHighLevelClient esClient) throws Exception {
// Get operation
final OperationType operationType = record.eventName();
// Obtain a reference to actual DynamoDB stream record
final StreamRecord streamRecord = record.dynamodb();
// Get ID. Assume single numeric attribute as partition key
final Map<String,AttributeValue> keys = streamRecord.keys();
final String recordId = keys.get("ID").n();
switch (operationType) {
case INSERT:
if (!streamRecord.hasNewImage()) {
throw new IllegalArgumentException("No new image when inserting");
}
Map<String,AttributeValue> newImage = streamRecord.newImage();
// Where toJson is defined here https://github.com/aaronanderson/aws-java-sdk-v2-utils/blob/master/src/main/java/DynamoDBUtil.java
// and included below
JsonObject jsonObject = toJson(newImage);
IndexRequest indexRequest = new IndexRequest(index, type, recordId);
indexRequest.source(jsonObject.toString(), XContentType.JSON);
IndexResponse indexResponse = esClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println("New content successfully indexed: " + indexResponse);
break;
case MODIFY:
if (!streamRecord.hasNewImage()) {
throw new IllegalArgumentException("No new image when updating");
}
Map<String,AttributeValue> newImage = streamRecord.newImage();
JsonObject jsonObject = toJson(newImage);
UpdateRequest updateRequest = new UpdateRequest(index, type, recordId);
request.doc(jsonObject.toString(), XContentType.JSON);
UpdateResponse updateResponse = esClient.update(updateRequest, RequestOptions.DEFAULT);
System.out.println("Content successfully updated: " + updateResponse);
break;
case REMOVE:
DeleteRequest deleteRequest = new DeleteRequest(index, type, recordId);
DeleteResponse deleteResponse = esClient.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println("Successfully removed: " + deleteResponse);
break;
default:
throw new UnsupportedOperationException("Operation type " + opetationType + " not supportd");
}
}
此类定义了
toJson
方法:
https://github.com/aaronanderson/aws-java-sdk-v2-utils/blob/master/src/main/java/DynamoDBUtil.java
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonString;
import javax.json.JsonStructure;
import javax.json.JsonValue;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
/** This is a utility for converting DynamoDB AttributeValues to and from Java JSON-P objects */
public class DynamoDBUtil {
public static void addList(String key, JsonObjectBuilder objectBuilder, List<JsonObject> items) {
if (!items.isEmpty()) {
JsonArrayBuilder builder = Json.createArrayBuilder();
items.forEach(i -> builder.add(i));
objectBuilder.add(key, builder.build());
}
}
public static JsonArray toJson(List<AttributeValue> attributeValues) {
if (attributeValues == null) {
return null;
}
JsonArrayBuilder valueBuilder = Json.createArrayBuilder();
for (AttributeValue a : attributeValues) {
add(toJson(a), valueBuilder);
}
return valueBuilder.build();
}
public static JsonObject toJson(Map<String, AttributeValue> attributeValues) {
if (attributeValues == null) {
return null;
}
JsonObjectBuilder valueBuilder = Json.createObjectBuilder();
for (Map.Entry<String, AttributeValue> a : attributeValues.entrySet()) {
add(a.getKey(), toJson(a.getValue()), valueBuilder);
}
return valueBuilder.build();
}
public static void add(String key, Object value, JsonObjectBuilder object) {
if (value instanceof JsonValue) {
object.add(key, (JsonValue) value);
// with json-p 1.0 can't create JsonString or JsonNumber so simply setting JsonValue not an option.
} else if (value instanceof String) {
object.add(key, (String) value);
} else if (value instanceof BigDecimal) {
object.add(key, (BigDecimal) value);
} else if (value instanceof Boolean) {
object.add(key, (Boolean) value);
} else if (value == null || value.equals(JsonValue.NULL)) {
object.addNull(key);
}
}
public static void add(Object value, JsonArrayBuilder array) {
if (value instanceof JsonValue) {
array.add((JsonValue) value);
} else if (value instanceof String) {
array.add((String) value);
} else if (value instanceof BigDecimal) {
array.add((BigDecimal) value);
} else if (value instanceof Boolean) {
array.add((Boolean) value);
} else if (value.equals(JsonValue.NULL)) {
array.addNull();
}
}
public static Object toJson(AttributeValue attributeValue) {
// with json-p 1.1 Json.createValue() can be used.
if (attributeValue == null) {
return null;
}
if (attributeValue.s() != null) {
return attributeValue.s();
}
if (attributeValue.n() != null) {
return new BigDecimal(attributeValue.n());
}
if (attributeValue.bool() != null) {
// return attributeValue.bool() ? JsonValue.TRUE : JsonValue.FALSE;
return attributeValue.bool();
}
if (attributeValue.b() != null) {
// return Base64.getEncoder().encodeToString(attributeValue.b().array());
return null;
}
if (attributeValue.nul() != null && attributeValue.nul()) {
return JsonValue.NULL;
}
if (!attributeValue.m().isEmpty()) {
return toJson(attributeValue.m());
}
if (!attributeValue.l().isEmpty()) {
return toJson(attributeValue.l());
}
if (!attributeValue.ss().isEmpty()) {
return attributeValue.ss();
}
if (!attributeValue.ns().isEmpty()) {
return attributeValue.ns();
}
if (!attributeValue.bs().isEmpty()) {
//return attributeValue.bs();
return null;
}
return null;
}
public static Map<String, AttributeValue> toAttribute(JsonObject jsonObject) {
Map<String, AttributeValue> attribute = new HashMap<>();
jsonObject.entrySet().forEach(e -> {
attribute.put(e.getKey(), toAttribute(e.getValue()));
});
return attribute;
}
public static List<AttributeValue> toAttribute(JsonArray jsonArray) {
List<AttributeValue> attributes = new LinkedList<>();
jsonArray.forEach(e -> {
attributes.add(toAttribute(e));
});
return attributes;
}
public static AttributeValue toAttribute(JsonValue jsonValue) {
if (jsonValue == null) {
return null;
}
switch (jsonValue.getValueType()) {
case STRING:
return AttributeValue.builder().s(((JsonString) jsonValue).getString()).build();
case OBJECT:
return AttributeValue.builder().m(toAttribute((JsonObject) jsonValue)).build();
case ARRAY:
return AttributeValue.builder().l(toAttribute((JsonArray) jsonValue)).build();
case NUMBER:
return AttributeValue.builder().n(((JsonNumber) jsonValue).toString()).build();
case TRUE:
return AttributeValue.builder().bool(true).build();
case FALSE:
return AttributeValue.builder().bool(false).build();
case NULL:
return AttributeValue.builder().nul(true).build();
}
return null;
}
public static AttributeValue compress(Map<String, AttributeValue> attributeValues) throws IOException {
return compress(toJson(attributeValues));
}
public static AttributeValue compress(List<AttributeValue> attributeValues) throws IOException {
return compress(toJson(attributeValues));
}
public static AttributeValue compress(JsonStructure jsonStructure) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Json.createWriter(outputStream).write(jsonStructure);
outputStream.close();
byte[] jsonBinary = outputStream.toByteArray();
outputStream = new ByteArrayOutputStream();
Deflater deflater = new Deflater();
deflater.setInput(jsonBinary);
deflater.finish();
byte[] buffer = new byte[1024];
while (!deflater.finished()) {
int count = deflater.deflate(buffer); // returns the generated code... index
outputStream.write(buffer, 0, count);
}
outputStream.close();
jsonBinary = outputStream.toByteArray();
return AttributeValue.builder().b(SdkBytes.fromByteArray(jsonBinary)).build();
}
public static JsonStructure decompress(AttributeValue attributeValue) throws IOException, DataFormatException {
Inflater inflater = new Inflater();
byte[] jsonBinary = attributeValue.b().asByteArray();
inflater.setInput(jsonBinary);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(jsonBinary.length);
byte[] buffer = new byte[1024];
while (!inflater.finished()) {
int count = inflater.inflate(buffer);
outputStream.write(buffer, 0, count);
}
outputStream.close();
byte[] output = outputStream.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(output);
return Json.createReader(bis).read();
}
}
此类是此
gist中最初引入的更新版本。
AtributeValue
序列化器提供
link。
关于java - 使用AWS开发工具包v2将DynamoDB转换为Elasticsearch?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64561687/
我有一个 k*n矩阵 X 和 k*k矩阵A。对于X的每一列,我想计算标量 X[:, i].T.dot(A).dot(X[:, i]) (或者,数学上, Xi' * A * Xi )。 目前,我有一个
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我是 VueJS 的新手。我已经使用 vuetify/webpack-ssr 模板创建了一个项目,现在我想创建一个登录页面,但是没有显示表单,控制台给了我以下信息: [Vue warn]: Unkno
我尝试将 value 插入到 C++ vector v 之前的第 i 元素(或元素 (i-1) 之后) )。代码很简单 v.insert(v.begin() + i, value); 我确信当 i 介
我需要显示使用合并排序算法排序的 vector 。然而,当我使用 v.begin() 时,我的 friend 使用 v.data() 来传递 vector 。他的代码运行良好,而我的却不行。请解释。
这是我的命令(url1、url2、url3、url4 是占位符): ffmpeg -i url1 -i url2 -i url3 -i url4 -filter_complex “[1:v:0] [1
我以前用过Vue,我知道怎么用v-for渲染元素序列,v-if或v-show有条件地显示元素,并且 v-model例如,控制段落的内容。 但现在我需要对 DOM 进行更精细的控制: 我有一个range
我正在学习所有权和借用。 borrow1 和borrow2 的区别在于在borrow2 打印时使用了&: fn borrow1(v: &Vec) { println!("{}", &v[10]
我找不到一种方法来选择不同的选项来渲染 v-for 中的文本。是否有可能或者我是否需要以不同的方式构建逻辑来执行类似于下面的代码的操作? // i
Iterable 的三个直接子类型是 Map , Seq , 和 Set .除了性能问题之外,似乎还有一个 Seq是从整数到值的映射,以及 Set是从值到 bool 值的映射(如果值在集合中,则为 t
我想应用一个计算方法,如果键存在则增加值,否则将 1。有 Map map = new HashMap<>(); 我不明白为什么 for (int i = 0; i v != null ? v++ :
标准(IEEE 754/C)是否保证以下代码断言永远不会失败? int main() { for ( /* all possible float / double values */ )
代码由Vue语言编写,使用Element-ui框架, 如果一个对象包含某些内容,则会显示该内容,如果不包含则禁用菜单按钮。 输出应该是这样的: a、b(禁用)、c、d、e 但我的是这样的: a、a(禁
如果我这样做: {{ morevalue }} {{ value }} v-else 中的跨度也会在第二个 V-FOR 上循环,即使它上面没有任何 v-for,为什么? 这是
如果我这样做: {{ morevalue }} {{ value }} v-else 中的跨度也会在第二个 V-FOR 上循环,即使它上面没有任何 v-for,为什么? 这是
我将 Vue.js 与 Vuetify 一起使用,我正在尝试使用 v-data-table 从后端加载菜单列表并使用 对其设置一些权限v-switches 但我在尝试 v-model 数组时遇到问题:
我在 Java 的流式操作中努力维护我想要的数据结构,这很可能是由于缺乏正确的理解和实践。 public class Main { public static void main(String
我正在尝试为匹配中的每个匹配呈现一些 HTML,但是,我不太确定 实际上是正确的。 更具体地说,我不确定我是否可以使用 v-bind:match='match'在与循环相同的元素上 v-for='ma
所以我想知道为什么这个 v-if 和 v-else 语句不起作用,为什么我要以不同的方式解决它。 代码如下 Required: Select a Workflow {{ isChain ?
我有一个 VueJS 组件 ,我在同一个模板中使用了两次来显示两组不同的数据。每个都显示在自己的 使用 v-if 切换的容器在导航选项卡上。 似乎这些组件被实例化为同一个实例。我调用 console
我是一名优秀的程序员,十分优秀!