AWS 的嵌套 GraphQL 突变 Amplify/AppSync
Nested GraphQL mutations with AWS Amplify/AppSync
我已经访问了 AWS 论坛,但我希望在这里得到更广泛受众的关注。我正在寻找有关以下 question.
的任何指导
我会post下面的问题:
您好,非常感谢您的帮助。
我是 Amplify/GraphQL 的新手,正在努力让突变发挥作用。具体来说,当我向模型添加连接时,它们永远不会出现在模拟 api 生成器中。如果我把它们写出来,他们会说“输入不存在”。我四处搜索,人们似乎说“在主要项目之前创建子项目,然后更新主要项目”,但我不希望那样。我有一个大型表单,其中包含多个多对多关系,它们都需要有效才能保存主表单。我不知道如何创建每个子项,然后再创建主项。
但是,这些项目列在响应的可用数据中。在下面的示例中,输入中缺少地址、股东、董事会成员。
None 个带有“@connection”的字段出现在创建 api 中作为输入。 help/guidance 我会拿走任何我能得到的。我似乎没有理解这里的核心内容。
这是我的模型:
type Company @model(queries: { get: "getEntity", list: "listEntities" }, subscriptions: null) {
id: ID!
name: String!
president: String
vicePresident: String
secretary: String
treasurer: String
shareholders: Shareholder @connection
boardOfDirectors: BoardMember @connection
addresses: [Address]! @connection
...
}
type Address @model{
id: ID!
line1: String!
line2: String
city: String!
postalCode: String!
state: State!
type: AddressType!
}
type BoardMember @model{
id: ID!
firstName: String!
lastName: String!
email: String!
}
type Shareholder @model {
id: ID!
firstName: String!
lastName: String!
numberOfShares: String!
user: User!
}
----一天后----
我已经取得了一些进步,但仍然对发生的事情缺乏一些了解。
我已将架构更新为:
type Company @model(queries: { get: "getEntity", list: "listEntities" }, subscriptions: null) {
id: ID!
name: String!
president: String
vicePresident: String
secretary: String
treasurer: String
...
address: Address @connection
...
}
type Address @model{
id: ID!
line1: String!
line2: String
city: String!
postalCode: String!
state: State!
type: AddressType!
}
我删除了我尝试的多对多关系,现在我仅限于一家只有 1 个地址的公司。我想这是一个未来的问题。但是,现在在输入列表中,'CompanyAddressId' 位于输入列表中。这表明它希望我在公司之前保存地址。地址只是公司的一部分,如果地址无效并且表单的其他部分失败并且用户退出,我不想保存地址。
我不明白为什么我不能一次写出所有字段?按照上面的模式,我还会有股东、董事会成员等。所以我必须先创建董事会成员和股东名单,然后才能创建公司?这似乎倒退了。
再一次,任何帮助我弄清楚我遗漏了什么的尝试都将不胜感激。
谢谢
--编辑--
我在资源管理器中看到的
-- 编辑 2--
这是基于您的示例的新生成的操作。您会看到 Company 现在获取一个地址 Id——我们之前讨论过。但这与股东无关。为了写出股东,我必须使用需要公司 ID 的 'createShareholder',但公司尚未创建。彻底糊涂了。
@engam 我希望你能帮助解决新问题。非常感谢!
以下是您可以尝试的一些概念:
对于@model 指令,请在不重命名查询的情况下进行尝试。 AWS Amplify 为自动生成的查询命名。例如,要获取公司,它将是 getCompany,对于列表,它将是 listCompanys。如果你还想给它起新的名字,你可以稍后再更改。
对于@connection 指令:
需要在连接的两个 table 上设置 @connection
。此外,如果您想要多对多连接,则需要添加第三个 table 来处理连接。当您的架构中有许多连接时,为连接命名也很有用。
只有您在架构中创建的标量类型、标准 schalars(如 String、Int、Float 和 Boolean)以及 AWS 特定的 schalars(如 AWSDateTime)才能用作架构中的 schalars。看看这个 link:
https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html
这是我认为您想要实现的一些示例:
type Company @model {
id: ID!
name: String
president: String
vicePresident: String
secretary: String
treasurer: String
shareholders: [Shareholder] @connection(name: "CompanySharholderConnection")
address: Address @connection(name: "CompanyAdressConnection") #one to many example
# you may add more connections/attributes ...
}
# table handling many-to-many connections between users and companies, called Shareholder.
type Shareholder @model {
id: ID!
company: Company @connection(name: "CompanySharholderConnection")
user: User @connection(name: "UserShareholderConnection")
numberOfShares: Int #or String
}
type User @model {
id: ID!
firstname: String
lastname: String
company: [Shareholder] @connection(name: "UserShareholderConnection")
#... add more attributes / connections here
}
# address table, one address may have many companies
type Address @model {
id: ID!
street: String
city: String
code: String
country: String
companies: [Company] @connection(name: "CompanyAdressConnection") #many-to-one connection
}
每个这种类型...@model 都会生成一个新的 dynamoDB table。此示例将使您可以创建多个公司和多个用户。要将用户添加为公司的股东,您只需要在Shareholder table中创建一个新项目,方法是创建一个新项目,ID为用户table,ID为公司里的公司table+加多少股。
编辑
请注意,当您在两个 table 之间生成连接时,amplify cli(使用 cloudformation 进行后端更改)将为一个或多个 dynamodb tables,让appsync可以高效的给你数据。
dynamodb 中的限制,使得当您编辑 table 时一次只能生成一个索引 (@connection)。我认为您可以在创建新的 table (@model) 时一次做更多的事情。因此,当您编辑一个或多个 table 时,在每次放大推送/放大发布之间,一次只能删除或添加一个连接。否则,当您推送更改时,cloudformation 将失败。清理起来可能一团糟。因此,我不得不多次删除整个环境,幸好不是在生产环境中。
更新
(我还使用 som 值更新了架构中的地址 table);
要在创建新公司时连接新地址,您首先必须在 dynamoDb 的地址 table 中创建一个新地址项。
从 appsync 生成的这个变化可能被命名为 createAddress() 并接受一个 createAddressInput。
创建地址后,您将收到整个新创建的项目,包括自动创建的 ID(如果您没有自己添加)。
现在您可以保存正在创建的新公司。 createCompany 突变采用的属性之一是您创建的地址的 ID,可能命名为 companyAddressId。在此处存储地址 ID。当您随后使用 getCompany 或 listCompanys 检索您的公司时,您将获得您公司的地址。
Javascript 示例:
const createCompany = async (address, company) => {
// api is name of the service with the mutations and queries
try {
const newaddress = await this.api.createAddress({street: address.street, city: address.city, country: address.country});
const newcompany = await this.api.createCompany({
name: company.name,
president: company.president,
...
companyAddressId: newaddress.id
})
} catch(error) {
throw error
}
}
// and to retrieve the company including the address, you have to update your graphql statement for your query:
const statement = `query ListCompanys($filter: ModelPartiFilterInput, $limit: Int, $nextToken: String) {
listCompanys(filter: $filter, limit: $limit, nextToken: $nextToken) {
__typename
id
name
president
...
address {
__typename
id
street
city
code
country
}
}
}
`
AppSync 现在将检索您的所有公司(取决于您的过滤器和限制)以及您已将地址连接到的那些公司的地址。
编辑 2
带有@model 的每种类型都是对aws 中dynamoDb table 的引用。因此,当您在两个 table 之间创建一对多关系时,当两个项目都是新的时,您首先必须在一对多关系中创建 'many'。在dynamoDb Company tables中,一个地址可以有很多公司,而一个公司只能有一个地址,你必须存储公司地址的id(dynamoDB主键)。您当然可以在前端生成地址 ID,并将其用于地址 ID,并将其用于公司的 addressCompanyId 并使用 await Promise.all([createAddress(...),createCompany(...))
但是如果一个失败,将创建另一个(但是通常 appsync api 是非常 stable,所以如果你发送的数据是正确的,它不会失败。
另一个解决方案,如果您通常不需要 create/update 多个 table 中的多个项目,您可以将地址直接存储在公司项目中。
type Company @model {
name: String
...
address: Address # or [Address] if you want more than one Address on the company
}
type Address {
street: String
postcode: String
city: string
}
那么地址类型将是 dynamoDb 中相同 table 中相同项目的一部分。但是您将失去对地址(或股东)进行查询以查找地址并查看哪些公司位于那里的能力(或者类似地查找一个人并查看该人拥有哪些公司的股份)。通常我不喜欢这种方法,因为它会将您的应用程序锁定在一个特定的事物上,并且以后很难创建新功能。
据我所知,不可能在一个 graphql (Amplify/AppSync) 突变中在多个 dynamoDb tables 中创建多个项目。因此,使用 Promise.all() 异步等待并在创建项目之前手动生成 id 属性前端可能是您的最佳选择。
我已经访问了 AWS 论坛,但我希望在这里得到更广泛受众的关注。我正在寻找有关以下 question.
的任何指导我会post下面的问题:
您好,非常感谢您的帮助。
我是 Amplify/GraphQL 的新手,正在努力让突变发挥作用。具体来说,当我向模型添加连接时,它们永远不会出现在模拟 api 生成器中。如果我把它们写出来,他们会说“输入不存在”。我四处搜索,人们似乎说“在主要项目之前创建子项目,然后更新主要项目”,但我不希望那样。我有一个大型表单,其中包含多个多对多关系,它们都需要有效才能保存主表单。我不知道如何创建每个子项,然后再创建主项。
但是,这些项目列在响应的可用数据中。在下面的示例中,输入中缺少地址、股东、董事会成员。
None 个带有“@connection”的字段出现在创建 api 中作为输入。 help/guidance 我会拿走任何我能得到的。我似乎没有理解这里的核心内容。
这是我的模型:
type Company @model(queries: { get: "getEntity", list: "listEntities" }, subscriptions: null) {
id: ID!
name: String!
president: String
vicePresident: String
secretary: String
treasurer: String
shareholders: Shareholder @connection
boardOfDirectors: BoardMember @connection
addresses: [Address]! @connection
...
}
type Address @model{
id: ID!
line1: String!
line2: String
city: String!
postalCode: String!
state: State!
type: AddressType!
}
type BoardMember @model{
id: ID!
firstName: String!
lastName: String!
email: String!
}
type Shareholder @model {
id: ID!
firstName: String!
lastName: String!
numberOfShares: String!
user: User!
}
----一天后----
我已经取得了一些进步,但仍然对发生的事情缺乏一些了解。
我已将架构更新为:
type Company @model(queries: { get: "getEntity", list: "listEntities" }, subscriptions: null) {
id: ID!
name: String!
president: String
vicePresident: String
secretary: String
treasurer: String
...
address: Address @connection
...
}
type Address @model{
id: ID!
line1: String!
line2: String
city: String!
postalCode: String!
state: State!
type: AddressType!
}
我删除了我尝试的多对多关系,现在我仅限于一家只有 1 个地址的公司。我想这是一个未来的问题。但是,现在在输入列表中,'CompanyAddressId' 位于输入列表中。这表明它希望我在公司之前保存地址。地址只是公司的一部分,如果地址无效并且表单的其他部分失败并且用户退出,我不想保存地址。
我不明白为什么我不能一次写出所有字段?按照上面的模式,我还会有股东、董事会成员等。所以我必须先创建董事会成员和股东名单,然后才能创建公司?这似乎倒退了。
再一次,任何帮助我弄清楚我遗漏了什么的尝试都将不胜感激。
谢谢
--编辑--
我在资源管理器中看到的
-- 编辑 2-- 这是基于您的示例的新生成的操作。您会看到 Company 现在获取一个地址 Id——我们之前讨论过。但这与股东无关。为了写出股东,我必须使用需要公司 ID 的 'createShareholder',但公司尚未创建。彻底糊涂了。
@engam 我希望你能帮助解决新问题。非常感谢!
以下是您可以尝试的一些概念:
对于@model 指令,请在不重命名查询的情况下进行尝试。 AWS Amplify 为自动生成的查询命名。例如,要获取公司,它将是 getCompany,对于列表,它将是 listCompanys。如果你还想给它起新的名字,你可以稍后再更改。
对于@connection 指令:
需要在连接的两个 table 上设置 @connection
。此外,如果您想要多对多连接,则需要添加第三个 table 来处理连接。当您的架构中有许多连接时,为连接命名也很有用。
只有您在架构中创建的标量类型、标准 schalars(如 String、Int、Float 和 Boolean)以及 AWS 特定的 schalars(如 AWSDateTime)才能用作架构中的 schalars。看看这个 link: https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html
这是我认为您想要实现的一些示例:
type Company @model {
id: ID!
name: String
president: String
vicePresident: String
secretary: String
treasurer: String
shareholders: [Shareholder] @connection(name: "CompanySharholderConnection")
address: Address @connection(name: "CompanyAdressConnection") #one to many example
# you may add more connections/attributes ...
}
# table handling many-to-many connections between users and companies, called Shareholder.
type Shareholder @model {
id: ID!
company: Company @connection(name: "CompanySharholderConnection")
user: User @connection(name: "UserShareholderConnection")
numberOfShares: Int #or String
}
type User @model {
id: ID!
firstname: String
lastname: String
company: [Shareholder] @connection(name: "UserShareholderConnection")
#... add more attributes / connections here
}
# address table, one address may have many companies
type Address @model {
id: ID!
street: String
city: String
code: String
country: String
companies: [Company] @connection(name: "CompanyAdressConnection") #many-to-one connection
}
每个这种类型...@model 都会生成一个新的 dynamoDB table。此示例将使您可以创建多个公司和多个用户。要将用户添加为公司的股东,您只需要在Shareholder table中创建一个新项目,方法是创建一个新项目,ID为用户table,ID为公司里的公司table+加多少股。
编辑
请注意,当您在两个 table 之间生成连接时,amplify cli(使用 cloudformation 进行后端更改)将为一个或多个 dynamodb tables,让appsync可以高效的给你数据。
dynamodb 中的限制,使得当您编辑 table 时一次只能生成一个索引 (@connection)。我认为您可以在创建新的 table (@model) 时一次做更多的事情。因此,当您编辑一个或多个 table 时,在每次放大推送/放大发布之间,一次只能删除或添加一个连接。否则,当您推送更改时,cloudformation 将失败。清理起来可能一团糟。因此,我不得不多次删除整个环境,幸好不是在生产环境中。
更新
(我还使用 som 值更新了架构中的地址 table); 要在创建新公司时连接新地址,您首先必须在 dynamoDb 的地址 table 中创建一个新地址项。
从 appsync 生成的这个变化可能被命名为 createAddress() 并接受一个 createAddressInput。
创建地址后,您将收到整个新创建的项目,包括自动创建的 ID(如果您没有自己添加)。
现在您可以保存正在创建的新公司。 createCompany 突变采用的属性之一是您创建的地址的 ID,可能命名为 companyAddressId。在此处存储地址 ID。当您随后使用 getCompany 或 listCompanys 检索您的公司时,您将获得您公司的地址。
Javascript 示例:
const createCompany = async (address, company) => {
// api is name of the service with the mutations and queries
try {
const newaddress = await this.api.createAddress({street: address.street, city: address.city, country: address.country});
const newcompany = await this.api.createCompany({
name: company.name,
president: company.president,
...
companyAddressId: newaddress.id
})
} catch(error) {
throw error
}
}
// and to retrieve the company including the address, you have to update your graphql statement for your query:
const statement = `query ListCompanys($filter: ModelPartiFilterInput, $limit: Int, $nextToken: String) {
listCompanys(filter: $filter, limit: $limit, nextToken: $nextToken) {
__typename
id
name
president
...
address {
__typename
id
street
city
code
country
}
}
}
`
AppSync 现在将检索您的所有公司(取决于您的过滤器和限制)以及您已将地址连接到的那些公司的地址。
编辑 2
带有@model 的每种类型都是对aws 中dynamoDb table 的引用。因此,当您在两个 table 之间创建一对多关系时,当两个项目都是新的时,您首先必须在一对多关系中创建 'many'。在dynamoDb Company tables中,一个地址可以有很多公司,而一个公司只能有一个地址,你必须存储公司地址的id(dynamoDB主键)。您当然可以在前端生成地址 ID,并将其用于地址 ID,并将其用于公司的 addressCompanyId 并使用 await Promise.all([createAddress(...),createCompany(...))
但是如果一个失败,将创建另一个(但是通常 appsync api 是非常 stable,所以如果你发送的数据是正确的,它不会失败。
另一个解决方案,如果您通常不需要 create/update 多个 table 中的多个项目,您可以将地址直接存储在公司项目中。
type Company @model {
name: String
...
address: Address # or [Address] if you want more than one Address on the company
}
type Address {
street: String
postcode: String
city: string
}
那么地址类型将是 dynamoDb 中相同 table 中相同项目的一部分。但是您将失去对地址(或股东)进行查询以查找地址并查看哪些公司位于那里的能力(或者类似地查找一个人并查看该人拥有哪些公司的股份)。通常我不喜欢这种方法,因为它会将您的应用程序锁定在一个特定的事物上,并且以后很难创建新功能。
据我所知,不可能在一个 graphql (Amplify/AppSync) 突变中在多个 dynamoDb tables 中创建多个项目。因此,使用 Promise.all() 异步等待并在创建项目之前手动生成 id 属性前端可能是您的最佳选择。