Amazon DynamoDB,在 Java 中使用筛选表达式和扫描操作

Amazon DyanamoDB ,Using filter expressions with scan operations in Java

我正在尝试获取所有价格大于某个值的商品,但无法正确使用过滤器表达式。

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
import com.amazonaws.services.dynamodbv2.model.ScanRequest;
import com.amazonaws.services.dynamodbv2.model.ScanResult;

public class QuerySample {
    // Setting up the client

    static AmazonDynamoDBClient db = new AmazonDynamoDBClient(
            new ProfileCredentialsProvider());
    // Setting up the DB
    static DynamoDB dynamoDB = new DynamoDB(db);

    public static void main(String a[]) {
        // Setting up the Region
        Region usWest = Region.getRegion(Regions.US_WEST_2);
        db.setRegion(usWest);
        Table table = dynamoDB.getTable("Thread");
        SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss.SSS");
        long time = (new Date()).getTime();
        Date date = new Date();
        date.setTime(time);
        System.out.println("The date is " + date);
        // ScanRequest scanRequest = new ScanRequest()
        // .withTableName("sys_ping");
        // ScanResult result = db.scan(scanRequest);
        // for (Map<String, AttributeValue> item : result.getItems()){
        // System.out.println(item);
        // }

        Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
        expressionAttributeValues.put(":val", "19");
        expressionAttributeValues.put(":val1",
                new AttributeValue().withN("2000"));
        ScanRequest scanRequest = new ScanRequest().withTableName(
                "ProductCatalog").withFilterExpression("Price >= :val");
        ScanResult result = db.scan(scanRequest);
        for (Map<String, AttributeValue> item : result.getItems()) {
            System.out.println(item);

        }

    }
}

它抛出以下运行时异常

线程中的异常"main" com.amazonaws.AmazonServiceException:无效的FilterExpression:未定义表达式中使用的表达式属性值;属性值::val(服务:AmazonDynamoDBv2;状态代码:400;错误代码:ValidationException;请求 ID:FEQBP55SPJIT60JVFPVO6N6BLBVV4KQNSO5AEMVJF66Q9ASUAAJG)

您在滥用 API。看看Map<String, Object> expressionAttributeValues

  1. 那里既有:val又有:val1
  2. 您没有将其传递给 new ScanRequest()

这是 DynamoDB API V2 的 Java 示例。假设我们有一个名为 Work 的 table 和一个名为 Archive 的列。存档列可以关闭或打开。

现在假设,我们只想查询未清项。使用 Java v2 和增强客户端,我们可以按如下方式执行此查询。

package com.example.dynamodb;

// snippet-start:[dynamodb.java2.mapping.scanEx.import]
import java.time.Instant;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Expression;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;
import software.amazon.awssdk.enhanced.dynamodb.model.ScanEnhancedRequest;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
// snippet-end:[dynamodb.java2.mapping.scanEx.import]

/*
    This code example uses an Expression object to select only Open items for the archive column.
    Prior to running this code example, create a Work table that contains the following fields:

    1.  id - Represents the key.
    2. date - Specifies the date the item was created.
    3. description - A value that describes the item.
    4. guide - A value that represents the deliverable being worked on.
    5. status - A value that describes the status.
    6. username - A value that represents the user who entered the item.
    7. archive - A value that represents whether this is an active or archive item. Specify Open and Closed items.
 */

public class EnhancedScanRecordsWithExpression {
    // Query the Record table
    public static void main(String[] args) {

        //Create a DynamoDbClient object
        Region region = Region.US_EAST_1;
        DynamoDbClient ddb = DynamoDbClient.builder()
                .region(region)
                .build();
        // Create a DynamoDbEnhancedClient and use the DynamoDbClient object
        DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();

        scan(enhancedClient);
    }

    // snippet-start:[dynamodb.java2.mapping.scanEx.main]
    public static void scan(DynamoDbEnhancedClient enhancedClient) {

        try {
            //Create a DynamoDbTable object
            DynamoDbTable<Work> table = enhancedClient.table("Work", TableSchema.fromBean(Work.class));

            AttributeValue attr = AttributeValue.builder()
                    .s("Open")
                    .build();

            // Get only Open items in the Work table
            Map<String, AttributeValue> myMap = new HashMap<>();
            myMap.put(":val1", attr);

            Map<String, String> myExMap = new HashMap<>();
            myExMap.put("#archive", "archive");

            // Set the Expression so only Closed items are queried from the Work table
            Expression expression = Expression.builder()
                    .expressionValues(myMap)
                    .expressionNames(myExMap)
                    .expression("#archive = :val1")
                    .build();

            ScanEnhancedRequest enhancedRequest = ScanEnhancedRequest.builder()
                    .filterExpression(expression)
                    .limit(15)
                    .build();

            // Get items in the Record table and write out the ID value
            Iterator<Work> results = table.scan().items().iterator();

            while (results.hasNext()) {

                Work rec = results.next();
                System.out.println("The record id is " + rec.getId());
            }

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        System.out.println("Done");
    }
    // snippet-end:[dynamodb.java2.mapping.scanEx.main]
}