循环引用 AWS appsync
Circular refrence AWS appsync
我想知道是否可以在 AWS Appsync 中进行循环引用?我已经搜索了很多但找不到它。像这样:
type Post {
title: String!
content: String!
user: User!
}
type Query {
allPosts: [Post!]
singlePost(id: String!): Post!
}
type User {
name: String!
posts: [Post!]
}
编辑(使用此处描述的逻辑尝试了 lambda https://youtu.be/bgq7FRSPDpI?list=PL55RiY5tL51rG1x02Yyj93iypUuHYXcB_&t=526)
这是 allPosts 的 lambda 解析器(将调用处理函数):
import * as sdk from "aws-sdk";
declare var process: {
env: {
TABLE_NAME: string;
};
};
interface Event {
info: {
fieldName: string;
parentTypeName: string;
variables: Record<string, any>;
};
}
const client = new sdk.DynamoDB.DocumentClient();
const getUser = (user_id: string): Record<string, any> | null => {
return client
.query({
TableName: process.env.TABLE_NAME,
KeyConditionExpression: "PK = :pk AND SK = :sk",
ExpressionAttributeValues: {
":pk": user_id,
":sk": "profile",
},
})
.promise()
.then(
(data) =>
data.Items?.map((item) => ({
...item.data,
posts: getPost.bind(null, item.PK),
}))[0]
)
.catch((err) => {
console.log(err);
return null;
});
};
const getPost = (user_id: string): Record<string, any> | null => {
return client
.query({
TableName: process.env.TABLE_NAME,
KeyConditionExpression: "SK = :sk AND pk = :pk",
ExpressionAttributeValues: {
":pk": user_id,
":sk": "profile",
},
})
.promise()
.then((data) =>
data.Items?.map((item) => ({
...item.data,
user: getUser.bind(null, item.PK),
}))
)
.catch((err) => {
console.log(err);
return null;
});
};
export const handler = async (event: Event) => {
if (event.info.fieldName === "allPosts") {
const data = await client
.query({
TableName: process.env.TABLE_NAME,
KeyConditionExpression: "#t = :sk",
IndexName: "GSI",
ProjectionExpression: "#d, PK",
ExpressionAttributeNames: {
"#t": "type",
"#d": "data",
},
ExpressionAttributeValues: {
":sk": "post",
},
})
.promise();
const result = data.Items?.map((item) => ({
...item.data,
user: getUser.bind(null, item.PK),
}));
console.log(data, result);
return result;
}
return;
// else if (event.fieldName === "singlePost") {
// }
};
用户字段具有此视频中的功能限制:https://youtu.be/bgq7FRSPDpI?list=PL55RiY5tL51rG1x02Yyj93iypUuHYXcB_&t=526
但是 lambda 响应没有返回有界函数。
[
{
"title": "post by user_123",
"content": "\n\nNew to this community. I need some help in designing the Amazon Dynamo DB table for my personal projects.\n\nOverview, this is a simple photo gallery application with following attributes.\n\nUserID\nPostID\nList item\nS3URL\nCaption\nLikes\nReports\nUploadTime\nI wish to perform the following queries:\n\nFor a given user, fetch 'N' most recent posts\nFor a given user, fetch 'N' most liked posts\nGive 'N' most recent posts (Newsfeed)\nGive 'N' most liked posts (Newsfeed)\nMy solution:"
},
{
"title": "another post by user_123",
"content": "\n\nNew to this community. I need some help in designing the Amazon Dynamo DB table for my personal projects.\n\nOverview, this is a simple photo gallery application with following attributes.\n\nUserID\nPostID\nList item\nS3URL\nCaption\nLikes\nReports\nUploadTime\nI wish to perform the following queries:\n\nFor a given user, fetch 'N' most recent posts\nFor a given user, fetch 'N' most liked posts\nGive 'N' most recent posts (Newsfeed)\nGive 'N' most liked posts (Newsfeed)\nMy solution:"
}
]
但我可以在日志中看到有界函数:
[
{
title: 'post by user_123',
content: '\n' +
'\n' +
'New to this community. I need some help in designing the Amazon Dynamo DB table for my personal projects.\n' +
'\n' +
'Overview, this is a simple photo gallery application with following attributes.\n' +
'\n' +
'UserID\n' +
'PostID\n' +
'List item\n' +
'S3URL\n' +
'Caption\n' +
'Likes\n' +
'Reports\n' +
'UploadTime\n' +
'I wish to perform the following queries:\n' +
'\n' +
"For a given user, fetch 'N' most recent posts\n" +
"For a given user, fetch 'N' most liked posts\n" +
"Give 'N' most recent posts (Newsfeed)\n" +
"Give 'N' most liked posts (Newsfeed)\n" +
'My solution:',
user: [Function: bound getUser]
},
{
title: 'another post by user_123',
content: '\n' +
'\n' +
'New to this community. I need some help in designing the Amazon Dynamo DB table for my personal projects.\n' +
'\n' +
'Overview, this is a simple photo gallery application with following attributes.\n' +
'\n' +
'UserID\n' +
'PostID\n' +
'List item\n' +
'S3URL\n' +
'Caption\n' +
'Likes\n' +
'Reports\n' +
'UploadTime\n' +
'I wish to perform the following queries:\n' +
'\n' +
"For a given user, fetch 'N' most recent posts\n" +
"For a given user, fetch 'N' most liked posts\n" +
"Give 'N' most recent posts (Newsfeed)\n" +
"Give 'N' most liked posts (Newsfeed)\n" +
'My solution:',
user: [Function: bound getUser]
}
]
TL;DR 是的,appsync 可以轻松处理嵌套或“循环”查询。关键的见解是,解析 user
字段后面的 User
类型不是 allPosts
处理程序的工作。相反,appsync 将调用 lambda 解析器 第二次 以获取 user
字段的 User
。我们需要在 lambda 中添加分支逻辑来处理第二次调用,其中 event.info.fieldName === "user"
.
// a switch statement inside your lambda function handler "routes" the request
switch (event.parentTypeName) {
case "Query":
switch (event.fieldName) {
case "allPosts":
// depends on your schema
const userID = event.arguments?.["id"]
// handle query, return [Post!], as per your schema
case "singlePost"
const postID = event.arguments?["id"]
// ditto, return Post!, as per your schema
}
case "Post":
switch (event.fieldName) {
case "user":
// event.source is a Post, details depend on your actual schema
const userID = event.source?.["userID"]
// make dynamo call to get the User and return a User, type that your graphql schema is expecting
}
case "User":
switch (event.fieldName) {
case "posts":
// event.source is a User, details depend on your actual schema
const userID = event.source?.["id"]
// fetch posts from dynamo, return [Post!], the type your graphql schema is expecting
}
default:
throw new Error("unhandled parent type")
}
Context:这个答案和问题一样,假设我们的数据源是 direct lambda resolver, meaning our function receives as an arg the full context object 并且我们不使用 VTL 模板。它还假定一般默认选择具有单个 lambda 解析器和巨大的 switch
语句来处理各种传入请求。
可解析字段由 appsync 单独解析。可解析字段具有解析器数据源。在我们的例子中,它是一个 lambda 函数。对于 appsync 遇到的每个可解析字段,appsync 将单独调用解析器。 (顺便说一句,我的猜测是你 已经 配置了 User
数据源。这将解开为什么 allPosts
不是 returning 的谜团用户结果。解析用户不是它的工作,你的 lambda 当前没有处理 event.info.fieldName
of user
).
设置解析器 aws 为我们提供了几种将解析器分配给字段的方法,包括在控制台(模式选项卡、附加按钮)和 cdk (add a LambdaDataSource to a ObjectType 中。
我们如何获得 user
ID? Appsync 为我们提供了 event
参数 user
PK/SK 信息我们的 dynamodb 调用。 event
为我们提供了很多信息,包括 fieldName
、parentTypeName
以及至关重要的 source
键以及父字段的值。 console.log
event
发现您需要处理的内容。
额外学分
问:appsync 会为以下查询调用我们的 lambda 多少次?
query allPosts(limit: 10) {
title
content
user {
name
}
}
A: 11 次。 allPosts
为 1 倍,user
为 10 倍。
现有技术 参见 and SO post 以获得类似的答案。
不要在家里尝试这个 理论上可以删除 User
类型的解析器,从而交给 allPosts
(和其他查询)对 return 用户的责任。由于查询 return 值的潜在深层嵌套,零增益相当复杂。
我想知道是否可以在 AWS Appsync 中进行循环引用?我已经搜索了很多但找不到它。像这样:
type Post {
title: String!
content: String!
user: User!
}
type Query {
allPosts: [Post!]
singlePost(id: String!): Post!
}
type User {
name: String!
posts: [Post!]
}
编辑(使用此处描述的逻辑尝试了 lambda https://youtu.be/bgq7FRSPDpI?list=PL55RiY5tL51rG1x02Yyj93iypUuHYXcB_&t=526)
这是 allPosts 的 lambda 解析器(将调用处理函数):
import * as sdk from "aws-sdk";
declare var process: {
env: {
TABLE_NAME: string;
};
};
interface Event {
info: {
fieldName: string;
parentTypeName: string;
variables: Record<string, any>;
};
}
const client = new sdk.DynamoDB.DocumentClient();
const getUser = (user_id: string): Record<string, any> | null => {
return client
.query({
TableName: process.env.TABLE_NAME,
KeyConditionExpression: "PK = :pk AND SK = :sk",
ExpressionAttributeValues: {
":pk": user_id,
":sk": "profile",
},
})
.promise()
.then(
(data) =>
data.Items?.map((item) => ({
...item.data,
posts: getPost.bind(null, item.PK),
}))[0]
)
.catch((err) => {
console.log(err);
return null;
});
};
const getPost = (user_id: string): Record<string, any> | null => {
return client
.query({
TableName: process.env.TABLE_NAME,
KeyConditionExpression: "SK = :sk AND pk = :pk",
ExpressionAttributeValues: {
":pk": user_id,
":sk": "profile",
},
})
.promise()
.then((data) =>
data.Items?.map((item) => ({
...item.data,
user: getUser.bind(null, item.PK),
}))
)
.catch((err) => {
console.log(err);
return null;
});
};
export const handler = async (event: Event) => {
if (event.info.fieldName === "allPosts") {
const data = await client
.query({
TableName: process.env.TABLE_NAME,
KeyConditionExpression: "#t = :sk",
IndexName: "GSI",
ProjectionExpression: "#d, PK",
ExpressionAttributeNames: {
"#t": "type",
"#d": "data",
},
ExpressionAttributeValues: {
":sk": "post",
},
})
.promise();
const result = data.Items?.map((item) => ({
...item.data,
user: getUser.bind(null, item.PK),
}));
console.log(data, result);
return result;
}
return;
// else if (event.fieldName === "singlePost") {
// }
};
用户字段具有此视频中的功能限制:https://youtu.be/bgq7FRSPDpI?list=PL55RiY5tL51rG1x02Yyj93iypUuHYXcB_&t=526
但是 lambda 响应没有返回有界函数。
[
{
"title": "post by user_123",
"content": "\n\nNew to this community. I need some help in designing the Amazon Dynamo DB table for my personal projects.\n\nOverview, this is a simple photo gallery application with following attributes.\n\nUserID\nPostID\nList item\nS3URL\nCaption\nLikes\nReports\nUploadTime\nI wish to perform the following queries:\n\nFor a given user, fetch 'N' most recent posts\nFor a given user, fetch 'N' most liked posts\nGive 'N' most recent posts (Newsfeed)\nGive 'N' most liked posts (Newsfeed)\nMy solution:"
},
{
"title": "another post by user_123",
"content": "\n\nNew to this community. I need some help in designing the Amazon Dynamo DB table for my personal projects.\n\nOverview, this is a simple photo gallery application with following attributes.\n\nUserID\nPostID\nList item\nS3URL\nCaption\nLikes\nReports\nUploadTime\nI wish to perform the following queries:\n\nFor a given user, fetch 'N' most recent posts\nFor a given user, fetch 'N' most liked posts\nGive 'N' most recent posts (Newsfeed)\nGive 'N' most liked posts (Newsfeed)\nMy solution:"
}
]
但我可以在日志中看到有界函数:
[
{
title: 'post by user_123',
content: '\n' +
'\n' +
'New to this community. I need some help in designing the Amazon Dynamo DB table for my personal projects.\n' +
'\n' +
'Overview, this is a simple photo gallery application with following attributes.\n' +
'\n' +
'UserID\n' +
'PostID\n' +
'List item\n' +
'S3URL\n' +
'Caption\n' +
'Likes\n' +
'Reports\n' +
'UploadTime\n' +
'I wish to perform the following queries:\n' +
'\n' +
"For a given user, fetch 'N' most recent posts\n" +
"For a given user, fetch 'N' most liked posts\n" +
"Give 'N' most recent posts (Newsfeed)\n" +
"Give 'N' most liked posts (Newsfeed)\n" +
'My solution:',
user: [Function: bound getUser]
},
{
title: 'another post by user_123',
content: '\n' +
'\n' +
'New to this community. I need some help in designing the Amazon Dynamo DB table for my personal projects.\n' +
'\n' +
'Overview, this is a simple photo gallery application with following attributes.\n' +
'\n' +
'UserID\n' +
'PostID\n' +
'List item\n' +
'S3URL\n' +
'Caption\n' +
'Likes\n' +
'Reports\n' +
'UploadTime\n' +
'I wish to perform the following queries:\n' +
'\n' +
"For a given user, fetch 'N' most recent posts\n" +
"For a given user, fetch 'N' most liked posts\n" +
"Give 'N' most recent posts (Newsfeed)\n" +
"Give 'N' most liked posts (Newsfeed)\n" +
'My solution:',
user: [Function: bound getUser]
}
]
TL;DR 是的,appsync 可以轻松处理嵌套或“循环”查询。关键的见解是,解析 user
字段后面的 User
类型不是 allPosts
处理程序的工作。相反,appsync 将调用 lambda 解析器 第二次 以获取 user
字段的 User
。我们需要在 lambda 中添加分支逻辑来处理第二次调用,其中 event.info.fieldName === "user"
.
// a switch statement inside your lambda function handler "routes" the request
switch (event.parentTypeName) {
case "Query":
switch (event.fieldName) {
case "allPosts":
// depends on your schema
const userID = event.arguments?.["id"]
// handle query, return [Post!], as per your schema
case "singlePost"
const postID = event.arguments?["id"]
// ditto, return Post!, as per your schema
}
case "Post":
switch (event.fieldName) {
case "user":
// event.source is a Post, details depend on your actual schema
const userID = event.source?.["userID"]
// make dynamo call to get the User and return a User, type that your graphql schema is expecting
}
case "User":
switch (event.fieldName) {
case "posts":
// event.source is a User, details depend on your actual schema
const userID = event.source?.["id"]
// fetch posts from dynamo, return [Post!], the type your graphql schema is expecting
}
default:
throw new Error("unhandled parent type")
}
Context:这个答案和问题一样,假设我们的数据源是 direct lambda resolver, meaning our function receives as an arg the full context object 并且我们不使用 VTL 模板。它还假定一般默认选择具有单个 lambda 解析器和巨大的 switch
语句来处理各种传入请求。
可解析字段由 appsync 单独解析。可解析字段具有解析器数据源。在我们的例子中,它是一个 lambda 函数。对于 appsync 遇到的每个可解析字段,appsync 将单独调用解析器。 (顺便说一句,我的猜测是你 已经 配置了 User
数据源。这将解开为什么 allPosts
不是 returning 的谜团用户结果。解析用户不是它的工作,你的 lambda 当前没有处理 event.info.fieldName
of user
).
设置解析器 aws 为我们提供了几种将解析器分配给字段的方法,包括在控制台(模式选项卡、附加按钮)和 cdk (add a LambdaDataSource to a ObjectType 中。
我们如何获得 user
ID? Appsync 为我们提供了 event
参数 user
PK/SK 信息我们的 dynamodb 调用。 event
为我们提供了很多信息,包括 fieldName
、parentTypeName
以及至关重要的 source
键以及父字段的值。 console.log
event
发现您需要处理的内容。
额外学分
问:appsync 会为以下查询调用我们的 lambda 多少次?
query allPosts(limit: 10) {
title
content
user {
name
}
}
A: 11 次。 allPosts
为 1 倍,user
为 10 倍。
现有技术 参见
不要在家里尝试这个 理论上可以删除 User
类型的解析器,从而交给 allPosts
(和其他查询)对 return 用户的责任。由于查询 return 值的潜在深层嵌套,零增益相当复杂。