DynamoDB “OR” 条件范围查询

DynamoDB “OR” conditional Range query

假设我的 table 看起来像:

Code    |StartDate  |EndDate    |Additional Attributes...

ABC     |11-24-2015 |11-26-2015 | ....

ABC     |12-12-2015 |12-15-2015 | ....

ABC     |10-05-2015 |10-10-2015 | ....

PQR     |03-24-2015 |03-27-2015 | ....

PQR     |05-04-2015 |05-08-2015 | ....

提供了一个代码 (c) 和一个日期范围 (x, y),我需要能够查询如下项目:

Query => (Code = c) AND ((StartDate BETWEEN x AND y) OR (EndDate BETWEEN x AND y))

我计划使用一个主键作为散列键和范围键(代码、开始日期)和一个额外的 LSI(结束日期)并对其进行查询。 我不确定是否有办法实现这一目标。我不想使用 SCAN 操作,因为它似乎扫描了整个 table,这可能非常昂贵。

另外,想在单个查询中实现这一点。

一种选择是使用 QUERYFilterExpression 来执行此操作。在这种情况下无需定义 LSI。您必须使用 EQ 运算符按 Hash Key 进行查询,然后使用过滤器表达式缩小结果范围。这是 Java SDK 的示例:

Table table = dynamoDB.getTable(tableName);

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":x", "11-24-2015");
expressionAttributeValues.put(":y", "11-26-2015");

QuerySpec spec = new QuerySpec()
    .withHashKey("Code", "CodeValueHere")
    .withFilterExpression("(StartDate between :x and :y) or (EndDate between :x and :y)")
    .withValueMap(expressionAttributeValues);


ItemCollection<QueryOutcome> items = table.query(spec);

Iterator<Item> iterator = items.iterator();

while (iterator.hasNext()) {
    System.out.println(iterator.next().toJSONPretty());
}

有关详细信息,请参阅 Specifying Conditions with Condition Expressions

此外,虽然之前的查询只使用了 Hash Key ,您仍然可以使用包含以下格式的日期的 Range Key 对记录进行分组:

开始日期#结束日期

Table结构:

Code    DateRange             |StartDate  |EndDate        
ABC     11-24-2015#11-26-2015 |11-24-2015 |11-26-2015  

ABC     12-12-2015#12-15-2015 |12-12-2015 |12-15-2015

ABC     10-05-2015#10-10-2015 |10-05-2015 |10-10-2015

PQR     03-24-2015#03-27-2015 |03-24-2015 |03-27-2015

PQR     05-04-2015#05-08-2015 |05-04-2015 |05-08-2015

这样如果您碰巧只按 Hash Key 查询,您仍然会得到按日期排序的记录。另外,我认为遵循有关明确日期的建议是个好主意 format.nu