目前我有一个包含以下字段的集合:
-
userId
-
otherUserId
-
date
-
status
对于我的Dynamo集合,我使用userId作为hashKey
,对于rangeKey
,我想使用日期:otherUserId。通过这样做,我可以检索按日期排序的所有userId条目,这很好。
然而,对于我的用例,我不应该有任何重复,这意味着我不应该在我的集合中有相同的userId-otherUserId
值。这意味着我应该先做一个查询来检查"夫妇"是否存在,如果需要的话删除它,然后做插入,对吧?
谢谢你的帮助:-)
我的用例的目标是存储userA访问userB的配置文件的时间。
现在,我想做的查询类型如下:
- 检索所有访问过UserA配置文件的UserB's,在一个唯一的(=没有双重UserB's)中,并按时间排序。
- 检索UserA和UserB的特定对访问
我认为你有很多选择,但这里有一个可能是基于你的应用程序是时间感知的假设,即你想查询交互在过去的N分钟,小时,天等。
hash_key = userA
range_key = [iso1860_timestamp][1]+userB+uuid
首先,uuid技巧是为了避免重写userA和userB之间的交互记录,而这些交互恰好发生在同一时间(可能取决于时钟的粒度/精度)。所以插入是安全的:没有重复,没有覆盖。
查询方面,下面是如何完成的:
- 检索所有访问过UserA配置文件的UserB's,在一个唯一的(=没有双重UserB's)中,并按时间排序。
query(hash_key=userA, range_key_condition=BEGIN(common_prefix))
where common_prefix
= 2013-01-01
这将检索时间范围内的所有记录,并进行排序(假设它们以正确的顺序插入)。然后在应用程序代码中对它们进行筛选,只保留与userB有关的那些。不幸的是,DynamoDB API不支持范围键条件列表(否则,您可以通过传递额外的CONTAINS userB条件来节省一些时间)。
- 检索UserA和UserB的特定对访问
query(hash_key=userA, range_key_condition=BEGINS(common_prefix))
如果我们可以假设你知道交互的时间戳,那么common_prefix
可能会更精确。
当然,这种设计应该根据您将要处理的数据流的属性进行评估。如果您可以(通常)为您的查询指定一个有意义的时间范围,那么它将是快速的,并且受到您在userA时间范围内记录的交互数量的限制。
如果你的应用程序不是面向时间的——我们可以假设用户通常只有很少的交互——你可能会切换到以下模式:
hash_key = userA
range_key = userB+[iso1860_timestamp][1]+uuid
这样就可以按用户进行查询了:
query(hash_key=userA, range_key_condition=BEGIN(userB))
这种替代方法将是快速的,并且在所有时间范围中受userA - userB交互的数量限制,这可能取决于您的应用程序。
基本上你应该检查示例数据并估计哪个方向对你的应用有意义。通过手动创建和维护其他表中的索引,还可以加快这两种方向(时间或用户)的速度——代价是更复杂的应用程序代码。
(历史版本:避免使用基于时间的键覆盖记录的技巧)在这种情况下,一个常见的技巧是使用生成的惟一id (uuid
)作为范围键的后缀。这样,您仍然可以使用BETWEEN
条件来执行query
调用,以检索在给定时间段内插入的记录,并且您不需要担心插入时的键冲突。