这是我的DynamoDB数据结构。
---------------------------------------------------------------------
id | author | status | content | createdAt
---------------------------------------------------------------------
id1 | user1 | PRIVATE | pcon | 2019-09-09T17:54:09.843Z
id1 | user1 | PUBLIC | hello | 2019-09-08T17:54:09.843Z
id2 | user2 | PUBLIC | world | 2019-09-07T17:54:09.843Z
id1 | user1 | PUBLIC | hello1 | 2019-09-07T17:54:09.843Z
---------------------------------------------------------------------
如何使用DynamoDB从每个用户查询最新的PUBLIC
内容?
期望的查询结果:
items[
{
id: id1,
author: user1,
status: PUBLIC,
content: hello,
createdAt: 2019-09-08T17:54:09.843Z
},
{
id: id2,
author: user2,
status: PUBLIC,
content: world,
createdAt: 2019-09-07T17:54:09.843Z
},
]
我可以使用以下代码获取所有PUBLIC
个项目,但找不到从中获取一个最新项目的方法。(放大自定义解析器映射模板)
{
"version": "2017-02-28",
"operation": "Query",
"query": {
"expression": "#privacy = :privacy",
"expressionNames": {
"#privacy": "privacy"
},
"expressionValues": {
":privacy": {
"S": "PUBLIC"
}
}
},
"scanIndexForward": #if( $context.args.sortDirection == "ASC" ) true #else false #end,
"limit": $limit,
"nextToken": #if( $context.args.nextToken ) "$context.args.nextToken" #else null #end,
"index": "privacy"
}
答案 0 :(得分:1)
您需要在其上引入第二个表和一个具有以下结构的GSI(全局二级索引):
userId
<-表的分区键category
<-GSI的分区键createdAt
<-GSI的排序键id
userId
属性是一个唯一标识用户的值(IIUC实际上可以是您帖子中描述的表中的author
字段)
category
属性最初可能看起来有些奇怪:它包含几个硬编码值之一。目前,我只能考虑一个这样的值:"public_content_page"
。尽管如此,即使将来不再出现任何新类别,也需要将此属性作为GSI的分区键(因此我们无法避免)。
createdAt
,id
属性与您的帖子中描述的表中的属性相同。
要按所需顺序获取商品,您需要按以下方式查询GSI:
{
"TableName": <your_table_name>,
"IndexName": <your_GSI_name>
"KeyConditionExpression": "category = :v1",
"ExpressionAttributeValues": {":v1": {"S": "public_content_page"}}
"ScanIndexForward": false,
}
因为该表的主键是userId
,所以该表每位用户只能容纳一个项目。
因为该表中的所有项目都具有相同的category
值,并且GSI的分区键为category
属性,所以查询GSI就是查询该表中的整个项目集。
由于createdAt
属性是GSI的排序键,因此该查询返回的结果将按时间顺序进行排序。
当然,您需要填充此表。基本上,每次您put()
/ update()
/ delete()
到第一个表(您的帖子中描述的那个)中的一项时,都需要在第二张表(我的答案中介绍的那张)。在该更新中,仅在新的update()
值大于项目中的ConditionExpression
值时,才需要使用createdAt
来覆盖项目。
您需要记住,第二个表的createdAt
极有可能无法执行(因为您的进程将在更新第一个表之后且在更新第二个表之前终止)。您可以执行定期扫描,以一定的定期计划从第一个表重建第二个表,也可以triggers)。
update()
。因此,为了获取实际项目的内容,您需要获取查询的结果,并使用查询返回的id
值在第一个表上执行多个get()
。您可以使用BatchGetItem在一个请求中执行多个id
操作。或者,您可以使用第二个表的不同结构:与其保留第一个表中的项get()
,不如保留第一个表中的项id
。这将使您摆脱其他content
的麻烦。另一方面,这将使财务成本更高(第二个表现在将存储更多数据),并使第二个表的更新更加频繁(因为get()
字段很可能是已编辑的字段通常,每次进行这样的修改都会导致对第二张表的更新)。
最后,您可以使用content
在单个事务中更新两个表,而不必在第二个表上执行update()
(这也需要进行lambda触发器/定期扫描)。不过,您仍然需要在TransactWriteItems
属性上使用条件。