使用多个字段动态扫描 DynamoDB 集合
Dynamically Scan DynamoDB collection using multiple fields
我正在创建一个使用 springboot 和 DynamoDB 作为数据库的 REST 服务。我有一个 StudentDTO class 具有以下字段和 Subject class 其主题信息为(键,值对):
@DynamoDBTable(tableName="Students")
Class Students{
@DynamoDBHashKey(attributeName="id")
int id;
String name;
int year;
@DynamoDBAttribute(attributeName="subjects")
List<Subjects> subjects; //it has serializedName("subjects")
//getter and setters
}
@DynamoDBDocument
Class Subjects{
String key;
String value;
}
我需要根据一些条件来获取数据。这些标准可能会有所不同。下面是一些例子:
- 可以获取关于名称、id 的数据 ("id":1,"name":"joe")
- 可以获取关于姓名、主题信息的数据 ("name":"joe",subjects:[{"key":"S1","value":"Geography"},{"key":"S2","value":"History"}]")
- 可能需要有关姓名、年份的数据
没有固定的条件组合可以用来构建查询。我尝试使用 DynamoDBScanExpression 但无法确定如何设置 filterExpression。
创建了一个(键,值)映射,如(,)
我可以像这样创建 attributeName 和 attributeValue(全部在 DynamoDBDAO.java 中):
Map<String, String> attributeNames = new HashMap<String, String>();
Map<String, AttributeValue> attributeValues = new HashMap<String, AttributeValue>();
StringJoiner filterExpression = new StringJoiner(" AND ");
if (null != json.getS_no()) {
StringBuilder expression = new StringBuilder();
attributeNames.put("#s_no", "s_no");
attributeValues.put(":sno", new AttributeValue().withN(json.getS_no()));
expression.append("#s_no").append(" ").append("<>").append(" ").append(":s_no");
filterExpression.add(expression);
}
if (null != json.getName()) {
StringBuilder expression = new StringBuilder();
attributeNames.put("#name", "name");
attributeValues.put(":name", new AttributeValue().withN(json.getName()));
expression.append("#name").append(" ").append("<>").append(" ").append(":name");
filterExpression.add(expression);
}
if(null != json.getSubjects()){
StringBuilder expression = new StringBuilder();
attributeNames.put("#subjects", "subjects");
attributeValues.put(":subjects", new AttributeValue().withS(map.keySet().toString()));
expression.append("#subjects").append(" ").append("IN").append(" ").append(":subjects");
}
...
and so on
扫描查询
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()
.withFilterExpression(filterExpression.toString()) // HERE CONDITION CAN CHANGE ACCORDING TO THE ATTRIBUTES IN THE INPUT.
.withExpressionAttributeNames(attributeNames)
.withExpressionAttributeValues(attributeValues);
List<DBMapper> records = Dynamomapper.scan(DBMapper.class, scanExpression);
但是在 SCAN() 函数中给出了异常:
com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException:Students[subjects]; could not unconvert subjects
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperTableModel.unconvert(DynamoDBMapperTableModel.java:271)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.privateMarshallIntoObject(DynamoDBMapper.java:456)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.marshallIntoObjects(DynamoDBMapper.java:484)
at com.amazonaws.services.dynamodbv2.datamodeling.PaginatedScanList.<init>(PaginatedScanList.java:64)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.scan(DynamoDBMapper.java:1458)
at com.amazonaws.services.dynamodbv2.datamodeling.AbstractDynamoDBMapper.scan(AbstractDynamoDBMapper.java:216)
at com.example.dynamodb.dao.DynamoDBDAO.findByAttributes(DynamoDBDAO.java:379)
求推荐。
看起来您在主题 class 的属性上缺少 @DynamoDBAttribute。
将您的主题 class 更改为以下内容应该可以正确反序列化:
@DynamoDBDocument
class Subjects {
@DynamoDBAttribute(attributeName="key")
String key;
@DynamoDBAttribute(attributeName="value")
String value;
// Getters/setters
}
此外,如果您计划获取姓名和年份属性,您可能还需要将 @DynamoDBAttribute 添加到学生 class 中的姓名和年份字段。
我得到的解决方案是向此 POJO 添加 No Argument 参数
我正在创建一个使用 springboot 和 DynamoDB 作为数据库的 REST 服务。我有一个 StudentDTO class 具有以下字段和 Subject class 其主题信息为(键,值对):
@DynamoDBTable(tableName="Students")
Class Students{
@DynamoDBHashKey(attributeName="id")
int id;
String name;
int year;
@DynamoDBAttribute(attributeName="subjects")
List<Subjects> subjects; //it has serializedName("subjects")
//getter and setters
}
@DynamoDBDocument
Class Subjects{
String key;
String value;
}
我需要根据一些条件来获取数据。这些标准可能会有所不同。下面是一些例子:
- 可以获取关于名称、id 的数据 ("id":1,"name":"joe")
- 可以获取关于姓名、主题信息的数据 ("name":"joe",subjects:[{"key":"S1","value":"Geography"},{"key":"S2","value":"History"}]")
- 可能需要有关姓名、年份的数据
没有固定的条件组合可以用来构建查询。我尝试使用 DynamoDBScanExpression 但无法确定如何设置 filterExpression。
创建了一个(键,值)映射,如(,)
我可以像这样创建 attributeName 和 attributeValue(全部在 DynamoDBDAO.java 中):
Map<String, String> attributeNames = new HashMap<String, String>();
Map<String, AttributeValue> attributeValues = new HashMap<String, AttributeValue>();
StringJoiner filterExpression = new StringJoiner(" AND ");
if (null != json.getS_no()) {
StringBuilder expression = new StringBuilder();
attributeNames.put("#s_no", "s_no");
attributeValues.put(":sno", new AttributeValue().withN(json.getS_no()));
expression.append("#s_no").append(" ").append("<>").append(" ").append(":s_no");
filterExpression.add(expression);
}
if (null != json.getName()) {
StringBuilder expression = new StringBuilder();
attributeNames.put("#name", "name");
attributeValues.put(":name", new AttributeValue().withN(json.getName()));
expression.append("#name").append(" ").append("<>").append(" ").append(":name");
filterExpression.add(expression);
}
if(null != json.getSubjects()){
StringBuilder expression = new StringBuilder();
attributeNames.put("#subjects", "subjects");
attributeValues.put(":subjects", new AttributeValue().withS(map.keySet().toString()));
expression.append("#subjects").append(" ").append("IN").append(" ").append(":subjects");
}
...
and so on
扫描查询
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()
.withFilterExpression(filterExpression.toString()) // HERE CONDITION CAN CHANGE ACCORDING TO THE ATTRIBUTES IN THE INPUT.
.withExpressionAttributeNames(attributeNames)
.withExpressionAttributeValues(attributeValues);
List<DBMapper> records = Dynamomapper.scan(DBMapper.class, scanExpression);
但是在 SCAN() 函数中给出了异常:
com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException:Students[subjects]; could not unconvert subjects
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperTableModel.unconvert(DynamoDBMapperTableModel.java:271)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.privateMarshallIntoObject(DynamoDBMapper.java:456)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.marshallIntoObjects(DynamoDBMapper.java:484)
at com.amazonaws.services.dynamodbv2.datamodeling.PaginatedScanList.<init>(PaginatedScanList.java:64)
at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.scan(DynamoDBMapper.java:1458)
at com.amazonaws.services.dynamodbv2.datamodeling.AbstractDynamoDBMapper.scan(AbstractDynamoDBMapper.java:216)
at com.example.dynamodb.dao.DynamoDBDAO.findByAttributes(DynamoDBDAO.java:379)
求推荐。
看起来您在主题 class 的属性上缺少 @DynamoDBAttribute。
将您的主题 class 更改为以下内容应该可以正确反序列化:
@DynamoDBDocument
class Subjects {
@DynamoDBAttribute(attributeName="key")
String key;
@DynamoDBAttribute(attributeName="value")
String value;
// Getters/setters
}
此外,如果您计划获取姓名和年份属性,您可能还需要将 @DynamoDBAttribute 添加到学生 class 中的姓名和年份字段。
我得到的解决方案是向此 POJO 添加 No Argument 参数