DynamoDB中条件写入的日期时间比较

时间:2015-06-05 10:44:01

标签: amazon-dynamodb

我目前正在使用DynamoDB。如果该记录的日期早于新记录日期字段,我想使用条件写入来更新记录。

有没有办法比较条件写入的DateTime类型?或者它目前仅适用于整数,字符串和流?

感谢。

2 个答案:

答案 0 :(得分:9)

由于您提到您使用的ISO-8601数据类型为conditional expression,因此您可以轻松使用{String<等比较运算符{3}}因为this answer中描述的词典排序。

这是一个快速示例,我使用Java 8的时间并针对DynamoDB Local运行它:

<=

输出:

import com.google.common.collect.ImmutableMap;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
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.Table;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import com.amazonaws.services.dynamodbv2.util.Tables;

import java.time.Instant;
import java.time.temporal.ChronoUnit;

public class DynamoDBStackoverflow {

    public static final String TABLE_NAME = "exampleTable";
    private static final String HASH_KEY = "hashAttributeName";

    public static void main(String[] args) {

        AWSCredentials awsCredentials = new BasicAWSCredentials("key", "secret");
        AmazonDynamoDB client = new AmazonDynamoDBClient(awsCredentials);
        client.setEndpoint("http://localhost:4000");
        DynamoDB dynamoDB = new DynamoDB(client);

        if (Tables.doesTableExist(client, TABLE_NAME)) {
            client.deleteTable(TABLE_NAME);
        }

        final CreateTableRequest createTableRequest = new CreateTableRequest()
            .withTableName(TABLE_NAME)
            .withKeySchema(new KeySchemaElement(HASH_KEY, KeyType.HASH))
            .withAttributeDefinitions(new AttributeDefinition(HASH_KEY, ScalarAttributeType.S))
            .withProvisionedThroughput(new ProvisionedThroughput(15L, 15L));
        final Table table = dynamoDB.createTable(createTableRequest);

        final Instant now = Instant.now();
        final Instant before = now.minus(10, ChronoUnit.MINUTES).truncatedTo(ChronoUnit.MINUTES);
        final Instant after = now.plus(10, ChronoUnit.MINUTES);
        System.out.println("Before: " + before.toString());
        System.out.println("Now: " + now.toString());
        System.out.println("After: " + after.toString());

        table.putItem(new Item().withPrimaryKey(HASH_KEY, "1")
                          .withString("dateField", before.toString()));
        table.putItem(new Item().withPrimaryKey(HASH_KEY, "2")
                          .withString("dateField", now.toString()));
        System.out.println("put items");
        table.scan().forEach(System.out::println);

        UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "1")
            .withConditionExpression("dateField < :beforeDate")
            .withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
            .withUpdateExpression("SET dateField = :beforeDate");

        try {
            table.updateItem(updateItemSpec);
            throw new RuntimeException();
        } catch (ConditionalCheckFailedException ccfe) {
            System.out.println("expected conditional write with < to fail when they are equal");
        }

        updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "2")
            .withConditionExpression("dateField < :beforeDate")
            .withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
            .withUpdateExpression("SET dateField = :beforeDate");

        try {
            table.updateItem(updateItemSpec);
            throw new RuntimeException();
        } catch (ConditionalCheckFailedException ccfe) {
            System.out.println("expected conditional write with < to fail when new is before");
        }

        updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "1")
            .withConditionExpression("dateField <= :beforeDate")
            .withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
            .withUpdateExpression("SET dateField = :beforeDate");

        try {
            table.updateItem(updateItemSpec);
        } catch (ConditionalCheckFailedException ccfe) {
            System.out.println("should not happen");
            throw new RuntimeException();
        }

        updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "2")
            .withConditionExpression("dateField <= :afterDate")
            .withValueMap(ImmutableMap.of(":afterDate", after.toString()))
            .withUpdateExpression("SET dateField = :afterDate");
        try {
            table.updateItem(updateItemSpec);
        } catch (ConditionalCheckFailedException ccfe) {
            System.out.println("should not happen");
            throw new RuntimeException();
        }

        System.out.println();
        System.out.println("after all updates");
        table.scan().forEach(System.out::println);
    }
}

答案 1 :(得分:1)

DynamoDB不了解日期。如果您将日期保存为纪元以来的ms / s,那么您可以使用算术<>=等。

如果您使用String表示,那么一切都取决于您是否可以找到正确的DynamoDB运算符来查询其中两个。

我个人使用前者,因此用微积分来做。