我想使用带有rails的amazon Dynamo DB。但我还没有找到实现分页的方法。
我将AWS::Record::HashModel
用作ORM。
这个ORM支持这样的限制:
People.limit(10).each {|person| ... }
但我无法弄清楚如何在Dynamo DB中实现以下MySql查询。
SELECT *
FROM `People`
LIMIT 1 , 30
答案 0 :(得分:26)
您使用LIMIT发出查询。如果返回的子集不包含完整的表,那么" LastEvaluatedKey"返回值。您在下一个查询中将此值用作ExclusiveStartKey。等等...
答案 1 :(得分:1)
您可以在查询中提供“页面大小”以设置结果集大小。 DynamoDB的响应包含“LastEvaluatedKey”,它将根据页面大小指示最后一个键。如果响应不包含'LastEvaluatedKey',则表示没有剩余的结果来获取。 在下次提取时使用'LastEvaluatedKey'作为'ExclusiveStartKey'。
我希望这会有所帮助。
答案 2 :(得分:0)
我遇到了类似的问题。
通用分页方法是,使用“起始索引”或“起始页”以及“页长”。
基于“ ExclusiveStartKey”和“ LastEvaluatedKey”的方法非常特定于DynamoDB。
我觉得应该在API客户端/ UI中隐藏DynamoDB的分页特定实现。
此外,如果应用程序是无服务器的,则使用Lambda之类的服务,将无法维护服务器上的状态。另一面是客户端的实现将变得非常复杂。
我采用了另一种方法,我认为这是通用的(而不是特定于DynamoDB)
当API客户端指定起始索引时,请从中获取所有键 该表并将其存储到数组中。
从数组中查找起始索引的键,即 由客户指定。
使用ExclusiveStartKey并获取记录数,如下 在页面长度中指定。
如果不存在起始索引参数,则不执行上述步骤 需要,我们不需要在扫描中指定ExclusiveStartKey 操作。
此解决方案有一些缺点-
当用户需要分页时,我们需要获取所有键 起始索引。
我们将需要额外的内存来存储ID和索引。 其他数据库扫描操作(一次或多次以获取 键)
但是我觉得对于使用我们的API的客户来说,这将是非常简单的方法。向后扫描将无缝运行。如果用户希望看到“第n个”页面,则可以。
答案 3 :(得分:0)
这是一个简单的复制粘贴运行概念证明(Node.js),用于使用dynamodb进行无状态正向/反向导航。综上所述;每个响应都包含导航历史记录,使用户可以明确并一致地请求下一页或上一页(当存在next / prev参数时):
GET /accounts -> first page
GET /accounts?next=A3r0ijKJ8 -> next page
GET /accounts?prev=R4tY69kUI -> previous page
注意事项:
// demo.js
const mockTable = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
const getPagedItems = (pageSize = 5, cursor = {}) => {
// Parse cursor
const keys = cursor.next || cursor.prev || [] // fwd first
let key = keys[keys.length-1] || null // eg ddb's PK
// Mock query (mimic dynamodb response)
const Items = mockTable.slice(parseInt(key) || 0, pageSize+key)
const LastEvaluatedKey = Items[Items.length-1] < mockTable.length
? Items[Items.length-1] : null
// Build response
const res = {items:Items}
if (keys.length > 0) // add reverse nav keys (if any)
res.prev = keys.slice(0, keys.length-1)
if (LastEvaluatedKey) // add forward nav keys (if any)
res.next = [...keys, LastEvaluatedKey]
return res
}
// Run test ------------------------------------
const runTest = () => {
const PAGE_SIZE = 6
let x = {}, i = 0
// Page to end
while (i == 0 || x.next) {
x = getPagedItems(PAGE_SIZE, {next:x.next})
console.log(`Page ${++i}: `, x.items)
}
// Page back to start
while (x.prev) {
x = getPagedItems(PAGE_SIZE, {prev:x.prev})
console.log(`Page ${--i}: `, x.items)
}
}
runTest()
答案 4 :(得分:0)
事实上,我遇到了同样的问题,我注意到 LastEvaluatedKey
和 ExclusiveStartKey
运行不佳,尤其是在使用 Scan
时,所以我解决了这样的问题。
代码如下
PS:我使用的是 python
first_index = ((page_no-1)*page_size)
second_index = (page_no*page_size)
if (second_index > len(response['Items'])):
second_index = len(response['Items'])
return {
'statusCode': 200,
'count': response['Count'],
'response': response['Items'][first_index:second_index]
}