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,这可能非常昂贵。
另外,想在单个查询中实现这一点。
一种选择是使用 QUERY
和 FilterExpression
来执行此操作。在这种情况下无需定义 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
假设我的 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,这可能非常昂贵。
另外,想在单个查询中实现这一点。
一种选择是使用 QUERY
和 FilterExpression
来执行此操作。在这种情况下无需定义 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