使用DynamoDBMapper进行投影表达

时间:2015-10-05 20:52:44

标签: amazon-web-services amazon-dynamodb

我有500个要使用500主键属性检索的项目,我想要检索每个项目的4个属性而不是所有属性。我在Java中使用DynamoDBMapper,但我无法找到将它们投影到特定数量的属性的方法。检索所有属性可能非常昂贵,因为其中一个属性可能非常大。有没有办法使用DynamoDBMapper获取所有这500个项目的4个属性?

2 个答案:

答案 0 :(得分:3)

是的,DynamoDBMapper支持在queryscan方法中使用ProjectionExpressions。我load没有看到任何支持。

以下是使用public <T> PaginatedQueryList<T> query(java.lang.Class<T> clazz, DynamoDBQueryExpression<T> queryExpression)并提供投影DynamoDBQueryExpression的示例。查看.withProjectionExpression("var1, #projectedVar")使用ExpressionAttributeNames作为一个属性的import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression; import com.amazonaws.services.dynamodbv2.datamodeling.PaginatedQueryList; import com.amazonaws.services.dynamodbv2.model.AttributeValue; import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; import com.amazonaws.services.dynamodbv2.util.Tables; import java.util.HashMap; import java.util.Map; public class MyTest { public static final String TABLE_NAME = "test_table"; public static void main(String[] args) throws Exception { final AmazonDynamoDB dynamodb = new AmazonDynamoDBClient(new BasicAWSCredentials("aws", "key")); dynamodb.setEndpoint("http://localhost:8000"); if (Tables.doesTableExist(dynamodb, TABLE_NAME)) { dynamodb.deleteTable(TABLE_NAME); } final DynamoDBMapper mapper = new DynamoDBMapper(dynamodb); final CreateTableRequest request = mapper.generateCreateTableRequest(MyClass.class) .withProvisionedThroughput(new ProvisionedThroughput(5L, 5L)); dynamodb.createTable(request); final MyClass myClass1 = new MyClass(); myClass1.setHash("H1"); myClass1.setRange("R1"); myClass1.setVar1("v1"); myClass1.setVar2("v2"); myClass1.setVar3("v3"); mapper.save(myClass1); myClass1.setRange("R2"); myClass1.setVar1("v4"); myClass1.setVar2("v5"); myClass1.setVar3("v6"); mapper.save(myClass1); myClass1.setRange("R3"); myClass1.setVar1("v7"); myClass1.setVar2("v8"); myClass1.setVar3("v9"); mapper.save(myClass1); final HashMap<String, String> expressionAttributeNames = new HashMap<>(); expressionAttributeNames.put("#myHash", "hash"); expressionAttributeNames.put("#projectedVar", "var3"); final Map<String, AttributeValue> expressionAttributeValues = new HashMap<>(); expressionAttributeValues.put(":hashValue", new AttributeValue("H1")); final DynamoDBQueryExpression<MyClass> queryExpression = new DynamoDBQueryExpression<MyClass>() .withKeyConditionExpression("#myHash = :hashValue") .withExpressionAttributeNames(expressionAttributeNames) .withExpressionAttributeValues(expressionAttributeValues) .withProjectionExpression("var1, #projectedVar"); final DynamoDBMapperConfig mapperConfig = new DynamoDBMapperConfig(DynamoDBMapperConfig.ConsistentReads.CONSISTENT); final PaginatedQueryList<MyClass> query = mapper.query(MyClass.class, queryExpression, mapperConfig); query.forEach(System.out::println); } } 。如果您需要检索不是顶级属性的属性,则必须查看DocumentPaths documentation

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBRangeKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;

@DynamoDBTable(tableName = MyTest.TABLE_NAME)
public class MyClass {
    private String hash;
    private String range;
    private String var1;
    private String var2;
    private String var3;

    @DynamoDBHashKey
    public String getHash() { return hash; }

    public void setHash(String hash) { this.hash = hash; }

    @DynamoDBRangeKey
    public String getRange() { return range; }

    public void setRange(String range) { this.range = range; }

    @DynamoDBAttribute
    public String getVar1() { return var1; }

    public void setVar1(String var1) { this.var1 = var1; }

    @DynamoDBAttribute
    public String getVar2() { return var2; }

    public void setVar2(String var2) { this.var2 = var2; }

    @DynamoDBAttribute
    public String getVar3() { return var3; }

    public void setVar3(String var3) { this.var3 = var3; }

    @Override
    public String toString() {
        return "MyClass{" +
                "hash='" + hash + '\'' +
                ", range='" + range + '\'' +
                ", var1='" + var1 + '\'' +
                ", var2='" + var2 + '\'' +
                ", var3='" + var3 + '\'' +
                '}';
    }
}
MyClass{hash='null', range='null', var1='v1', var2='null', var3='v3'}
MyClass{hash='null', range='null', var1='v4', var2='null', var3='v6'}
MyClass{hash='null', range='null', var1='v7', var2='null', var3='v9'}

输出结果显示只检索了投影属性:

{{1}}

答案 1 :(得分:0)

您可以使用DynamoDB Table实例的重载scan操作,并将过滤器表达式保留为空。 以下示例仅为每个表项检索属性idcountry,即使每个记录具有更多的属性。它是 Kotlin ,但在 Java 中将以相同的方式工作。当然,这会绕过Mapper,但是将结果映射到仅包含所需属性的自定义DTO中应该很容易。

val table = com.amazonaws.services.dynamodbv2.document.DynamoDB(myClient).getTable("places")
val items = table.scan(null,"id,country",null,null) // filterExpression is null
val iterator: Iterator<Item> = items.iterator()
while (iterator.hasNext()) {
    log.debug(iterator.next().toJSONPretty()) // prints only id and country 
}