繁体   English   中英

DynamoDB-查询而不是扫描-如何使用随机生成的密钥实现

[英]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);

  • 我可以使用这种组合分区键的通配符之类的东西吗? (类似:“ *#myGreatUser”)
  • 有关数据库设置和其他注释作为关键元素的其他建议?
  • 也许是可以使用查询而不是扫描的索引?
  • 也许有人为这种用例提供​​了可行的示例?

您只需要切换分区键和排序键即可。

@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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM