![](/img/trans.png)
[英]Spring Data DynamoDB - Respository performing scan instead of query
[英]DynamoDB - Query instead of Scan - how to achive with random generated key
设定
我在Java和DynamoDB(DynamoDB Mapper)批注中具有下表:
@DynamoDBTable(tableName="myentity")
public class MyEntity {
@DynamoDBHashKey
@DynamoDBAutoGeneratedKey
private String id;
@DynamoDBIndexHashKey()
//@DynamoDBIndexRangeKey
private String userId;
private Date eventDate;
保存时会随机生成该id
,并且多个实体可以使用相同的userId
。
通过Web GUI定义的表如下:主分区键:id(字符串)主排序键:userId(字符串)
问题
我想使用查询而不是扫描来获取一个userId的所有实体。
查询-不能这样工作:
public List<MyEntity> findByUserIdQuery(String userId) {
Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();
eav.put(":val1", new AttributeValue().withS(userId));
DynamoDBQueryExpression<MyEntity> queryExpression = new DynamoDBQueryExpression<MyEntity>()
.withKeyConditionExpression("userId = :val1").withExpressionAttributeValues(eav);
List<MyEntity> list = mapper.query(MyEntity.class, queryExpression);
我当然知道:
com.amazonaws.AmazonServiceException: Query condition missed key schema element: id (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: 123) at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1305)
因为我想读取数据时不知道生成的ID。
解决方法
相反,我使用:
public List<MyEntity> findByOwner(String userId){
Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();
eav.put(":val1", new AttributeValue().withS(userId));
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression()
.withFilterExpression("userId = :val1").withExpressionAttributeValues(eav);
List<MyEntity> list = mapper.scan(MyEntity.class, scanExpression);
可能的解决方案
问题在于,我永远不知道为我拥有的元素随机生成的密钥。 当我想阅读时,我只知道userId,并且想拥有它们的所有实体。
我在这里观看了示例: https : //docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.QueryScanExample.html ...但是他们始终知道搜索内容的关键。 他们正在使用这样的组合键:
String partitionKey = forumName + "#" + threadSubject;*
eav.put(":val1", new AttributeValue().withS(partitionKey))
Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();
DynamoDBQueryExpression<Reply> queryExpression = new DynamoDBQueryExpression<Reply>()
.withKeyConditionExpression("Id = :val1 and ReplyDateTime > :val2").withExpressionAttributeValues(eav);
题
您只需要切换分区键和排序键即可。
@DynamoDBTable(tableName="myentity")
public class MyEntity {
@DynamoDBRangeKey
@DynamoDBAutoGeneratedKey
private String id;
@DynamoDBHashKey
private String userId;
private Date eventDate;
然后使用查询
public List<MyEntity> findByUserIdQuery(String userId) {
Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();
eav.put(":val1", new AttributeValue().withS(userId));
DynamoDBQueryExpression<MyEntity> queryExpression = new DynamoDBQueryExpression<MyEntity>()
.withKeyConditionExpression("userId = :val1").withExpressionAttributeValues(eav);
List<MyEntity> list = mapper.query(MyEntity.class, queryExpression);
顺便说一句,您提到您认为排序键是userId,但是在提供的示例中,您具有id的主哈希键和userid的全局二级索引哈希键。 没有排序键。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.