有什么想法如何从 DynamoDB 表中随机选择项目/记录吗?我不认为 API 中对此有任何规定。
我考虑过维护一个 NumericId|MyOtherKey (“NumericIdTable”)表,然后生成一个 0 到我拥有的记录总数之间的随机数,然后从 NumericIdTable 获取该项目,但从长远来看它不会起作用.
欢迎想法/想法。
我想出的一种从 DynamoDB 表中随机选择项目的方法:
例如,如果您使用 UUID 作为 RangeKey 的标识符,您可以获得如下随机项目
RandomRangeKey = new UUID
RandomItem = Query( "HashKeyValue": "KeyOfRandomItems",
"RangeKeyCondition": { "AttributeValueList":
"RandomRangeKey",
"ComparisonOperator":"GT"},
"Limit": 1 )
这样你就得到一个随机物品并且只消耗1个读取容量。
通过生成比表中使用的最小 UUID 更小的 UUID,有可能会错过随机变量的第一个查询。这个机会会随着表的扩大而缩小,您可以使用同一个随机键上的 SmallerThan 比较轻松地发送另一个请求,从而确保随机项目的命中。
如果您的 Tabledesign 不允许可随机化的 RangeKeys,您可以按照您的方法创建一个单独的 RandomItem 表并将 ID 存储在可随机化的 RangeKey 下。可能的表结构是
*RandomItemTable
TableName - HashKey
UUID - Rangekey
ItemId
请记住,对于这种方法,您需要管理原始表和随机化表之间的冗余。
如果您使用 GUID 作为表的哈希键,您可以执行以下操作:
var client = new AmazonDynamoDBClient();
var lastKeyEvaluated = new Dictionary<string, AttributeValue>()
{
{ "YOUR_HASH_KEY", new AttributeValue(Guid.NewGuid().ToString()) }
};
var request = new ScanRequest()
{
TableName = YOUR_TABLE_NAME,
ExclusiveStartKey = lastKeyEvaluated,
Limit = 1
};
var response = client.Scan(request);
这每次都会给你一个随机记录,因为它会生成一个随机 GUID 作为最后的 KeyEvaluated。
天真的方法是 1)使用describe table调用来获取该表中的N(总行数) 2)选择1到N之间的随机数i 3)扫描。停下来,直到你看到我行
我正在考虑更好的方法来做到这一点。当我有好的答案时我会更新。
一种简单有效的方法:
ProjectionExpression
只检索您的主分区键。
我通过添加一个 GSI(全局二级索引)来解决这个问题,它的哈希键代表一大类可供选择的项目(该类别不需要分布!)和一个具有随机值的排序键。
查询此 GSI 会产生高效的随机结果(约 90KB 数据库中的每个请求 0.5 RCU,仅扫描单个项目)。
我在下面使用的查询:
response = table.query(
Limit=1,
IndexName="my_index",
KeyConditionExpression=Key("type").eq("Q") & Key(random_property).gt(Decimal(str(Random().random()))),
ReturnConsumedCapacity='TOTAL'
)
如果从随机 id 中选择下一个最大的记录,如果两个 id 非常接近,会发生什么情况?还是说距离很远呢?这将影响选择 id 的概率。事实上,如果 id 之间的距离不是同质的,那么我们在 id 上就会有非同质的概率。
要解决此问题,您可以选择 50 条记录而不是 1 条。请求后,从这 50 条记录中随机选择一条。这将平均 50 条记录之间的距离,这应该会导致 id 之间的概率更加均匀。
然后,如果我们接近最大的 id,请说 n
< 50 from the top, the probability will also tend to be higher as you will be selecting between less than 50 records (only n).
只需查询最小的 50-n 条记录并将它们添加到 ids 中以供选择。