[英]Dynamodb design recommendations for partial comparisons
我目前有一个包含以下列的 Dynamodb 表 - Id(分区键)、NativeTimestampAndPath(范围键)、EntryTimestamp(属性)。 目前没有二级索引。
示例数据如下所示:
Id (Partition Key) | NativeTimestampAndPath (Range Key) | EntryTimestamp
event1#type1#eventid1 | 1960-01-01T00:00:00Z#event/event_name=event_1/event_type=type=1/day=15/eventid1-file1.json | 2012-01-15T00:00:00Z
event1#type1#eventid1 | 1970-01-01T00:00:00Z#event/event_name=event_1/event_type=type=1/day=16/eventid1-file2.json | 2012-01-16T00:00:00Z
event2#type1#eventid2 | 1970-01-01T00:00:00Z#event/event_name=event_2/event_type=type=1/day=17/eventid2-file1.json | 2012-01-17T00:00:00Z
event2#type1#eventid2 | 2000-01-01T00:00:00Z#event/event_name=event_2/event_type=type=1/day=18/eventid2-file2.json | 2012-01-18T00:00:00Z
所需的访问模式:
Id
的NativeTimestampAndPath
值在表中尚不存在,则有条件地插入到表中。Id
的所有NativeTimestampAndPath
值。Id
的所有NativeTimestampAndPath
值,这些值equal/greater than/greater than or equal/less/less than or equal
给定时间戳。 例如,如果我给定的时间戳是1970-01-01T00:00:00Z
并且条件是查找包含小于或等于给定时间戳的时间戳的所有NativeTimestampAndPath
,则搜索查询应仅返回上表中的前 3 行。Id
的所有NativeTimestampAndPath
值,并仅返回 1 个包含所有最大/最小时间戳的NativeTimestampAndPath
值。 总之,模式 3 和模式 4 只需要比较NativeTimestampAndPath
列值的时间戳部分。
在实现此比较逻辑时,我注意到我得到的equal/greater than/greater than or equal/less/less than or equal
条件的结果不准确,因为 Dynamodb 正在将给定的时间戳与整个值(包括时间戳和路径)进行比较NativeTimestampAndPath
列。 不准确的结果是词法比较的结果,而不是时间戳与时间戳比较的结果。
比较逻辑代码:
DynamoDBQueryExpression<Event> queryExpression = new DynamoDBQueryExpression<Event> ();
queryExpression
.withHashKeyValues (event)
.withConsistentRead (false);
queryExpression.setLimit (500);
FilterType.Conditional operator = filterDto.getTimestampOperator (); // comparison condition string
Instant givenTimestamp = filterDto.getTimestamp (); // given timestamp
if (operator != null && givenTimestamp != null) {
Condition rangeKeyCondition = new Condition ();
switch (operator) {
case eq:
rangeKeyCondition.withComparisonOperator (ComparisonOperator.BEGINS_WITH);
break;
case gt:
rangeKeyCondition.withComparisonOperator (ComparisonOperator.GT);
break;
case ge:
rangeKeyCondition.withComparisonOperator (ComparisonOperator.GE);
break;
case lt:
rangeKeyCondition.withComparisonOperator (ComparisonOperator.LT);
break;
case le:
rangeKeyCondition.withComparisonOperator (ComparisonOperator.LE.toString ());
break;
}
rangeKeyCondition.withAttributeValueList (new AttributeValue ().withS (String.valueOf (givenTimestamp)));
queryExpression.withRangeKeyCondition ("NativeTimestampAndPath", rangeKeyCondition);
}
FilterType.Aggregate aggregate = filterDto.getTimestampAggregator (); //specifies if max or min is required
if (aggregate != null) {
queryExpression.setLimit (1);
switch (aggregate) {
case max:
queryExpression.setScanIndexForward (false);
break;
case min:
queryExpression.setScanIndexForward (true);
break;
}
}
QueryResultPage<Event> paginated;
List<Event> result = new ArrayList<> ();
do {
paginated = dbMapper.queryPage (Event.class, queryExpression);
result.addAll (paginated.getResults ());
queryExpression.setExclusiveStartKey (paginated.getLastEvaluatedKey ());
} while (paginated.getLastEvaluatedKey () != null && aggregate == null);
return result;
假设我想:
Id
保留为分区键,将NativeTimestampAndPath
为范围键我可以对该 Dynamodb 设计做些什么来满足所需的访问模式条件? 非常感谢任何建议。 谢谢!
是的,排序键将被视为一个字符串。 1970-01-01T00:00:00Z#event/event_name=event_1/event_type=type=1/day=16/eventid1-file2.json
小于或等于1970-01-01T00:00:00Z
? 不,它在词法排序上稍晚一些。 如果您在时间戳之后有额外的数据,则不可能在此处直接包含任何相等性期望。
这是诀窍。 那个长字符串是否小于1970-01-01T00:00:00Z$
? 是的。 因为$是ASCII中#上面的一个字符,所以。 小于这个带有美元符号的值实际上将被视为小于或等于。 您可以使用 ! 对于另一个方向。
我不确定您对#4 的看法是什么。 您可以使用ScanIndexForward
指定Limit
和控制方向。 时间戳相同的关系将是随机选择的,但这与此处的数据 model 无关。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.