amazon-web-services - 将不同的排序键响应映射到 Appsync 架构值
问题描述
所以这是我的架构:
type Model {
PartitionKey: ID!
Name: String
Version: Int
FBX: String
# ms since epoch
CreatedAt: AWSTimestamp
Description: String
Tags: [String]
}
type Query {
getAllModels(count: Int, nextToken: String): PaginatedModels!
}
type PaginatedModels {
models: [Model!]!
nextToken: String
}
我想调用“getAllModels”并填写所有数据,并填写所有标签。
但事情就是这样。标签通过排序键存储。像这样
PartionKey | SortKey
Model-0 | Model-0
Model-0 | Tag-Tree
Model-0 | Tag-Building
Tags: [String]
是否可以通过 DynamoDB 解析器将“标签”排序键转换为架构中的数组?或者我必须通过 lambda 做一些额外的事情吗?还是有更聪明的方法来做到这一点?
解决方案
澄清一下,您是否在 DynamoDB 中存储这样的对象:
{ PartitionKey (HASH), Tag (SortKey), Name, Version, FBX, CreatedAt, Description }
并使用 DynamoDB 查询操作来获取给定 HashKey 的所有行。
Query #PartitionKey = :PartitionKey
并返回一个对象列表,其中一些具有不同的“Tag”值,其中一个是“Model-0”(也就是与分区键相同的值),我假设记录包含该记录的所有其他值。例如
[
{ PartitionKey, Tag: 'ValueOfPartitionKey', Name, Version, FBX, CreatedAt, ... },
{ PartitionKey, Tag: 'Tag-Tree' },
{ PartitionKey: Tag: 'Tag-Building' }
]
您绝对可以轻松编写解析器逻辑,将模型对象列表减少为具有“标签”列表的单个对象。让我们从单个项目开始,看看如何实现getModel(id: ID!): Model
查询:
首先定义将获取分区键的所有行的响应映射模板:
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
"expression": "#PartitionKey = :id",
"expressionValues" : {
":id" : {
"S" : "${ctx.args.id}"
}
},
"expressionNames": {
"#PartitionKey": "PartitionKey" # whatever the table hash key is
}
},
# The limit will have to be sufficiently large to get all rows for a key
"limit": $util.defaultIfNull(${ctx.args.limit}, 100)
}
然后,要返回将“标签”简化为“标签”的单个模型对象,您可以使用此响应映射模板:
#set($tags = [])
#set($result = {})
#foreach( $item in $ctx.result.items )
#if($item.PartitionKey == $item.Tag)
#set($result = $item)
#else
$util.qr($tags.add($item.Tag))
#end
#end
$util.qr($result.put("Tags", $tags))
$util.toJson($result)
这将返回如下响应:
{
"PartitionKey": "...",
"Name": "...",
"Tags": ["Tag-Tree", "Tag-Building"],
}
从根本上说,我认为这没有问题,但它的有效性取决于您的查询模式。将此扩展到 getAll 使用是可行的,但需要进行一些更改,并且很可能是一个非常低效的扫描操作,因为该表将很少包含实际信息,因为许多记录实际上只是标签。您可以使用 GSI 轻松缓解这种情况,但更多 GSI 意味着更多美元。
作为替代方法,您可以将标签存储在不同的“标签”表中。这样,您只需将模型信息存储在 Model 表中,将标签信息存储在 Tag 表中,并利用 GraphQL 为您执行连接。在这种方法中,Query.getAllModels对 Model 表执行“扫描”(或 Query),然后有一个Model.Tags解析器对 Tag 表(HK:ModelPartitionKey,SK:Tag)执行查询。然后,您可以获取一个模型的所有标签,然后创建一个 GSI 来获取一个标签的所有模型。您确实需要考虑,现在每个模型都会调用一次嵌套的Model.Tag查询,但是查询操作很快,而且我已经看到这在实践中运行良好。
希望这可以帮助 :)
推荐阅读
- python - df.sort_values 不是排序表(python/pandas)
- java - 如何调试 jbehave 故事运行的 selenium 远程 Web 驱动程序?
- c++ - 迷宫求解程序的回溯逻辑错误
- javascript - ng-circle-progress 组件仅在属性 renderOnClick 属性设置为 true 时有效
- postgresql - 检索具有给定列表中不存在的列值的行
- c# - 使游戏对象加载和活动加载屏幕同时运行
- java - 如果我更改了 XML 清单中的启动器活动,则应用程序重新启动
- java - java.lang.ClassNotFoundException:没有找到类“android.view.View$OnUnhandledKeyEventListener
- django - Wagtail - 非页面对象的修订
- docker - 构建我的 docker 文件时,我收到一个返回的非零代码:8