我是 Amplify、React 和 GraphQL 的新手。我正在寻找正确的方法来进行表之间具有@hasMany 关系的突变(对于上下文,我正在使用多表解决方案,因为这似乎最适合 Amplify)。
我正在尝试构建一个应用程序,它有一个用户,每个用户有几个孩子,每个孩子都有故事......我完全不知道如何在多个表之间建立这个 @hasMany 连接和更新。
这是我的 schema.graphql:
type User @model @auth(rules: [{allow: owner}]) {
id: ID!
email: String! @index(name: "byEmail", queryField: "userByEmail", sortKeyFields: ["id"])
children: [Child] @hasMany
settings: String
lastInteraction: String
}
type Child @model @auth(rules: [{allow: owner}]) {
id: ID!
name: String!
age: String!
commonNoun: String!
user: User @belongsTo
stories: [Story] @hasMany
}
type Story @model @auth(rules: [{allow: owner}]) {
id: ID!
child: Child @belongsTo
status: String
storyType: String
storyData: String!
}
我已经能够成功创建一个用户和一个孩子,但现在我想将两者联系起来。到目前为止,这是我创建用户的代码:
export async function createNewUserinDB(userEmail) {
const data = {
email: userEmail
};
const userCreationResponse = await API.graphql({
query: createUser,
variables: { input: data },
authMode: "AMAZON_COGNITO_USER_POOLS"
}).then(response => {
console.log(response);
return response;
}).catch(e => {
console.log("catch");
console.log(e);
return null;
});
return(userCreationResponse);
}
为了创造一个孩子:
async function createChildinDB(childAge, childName, childCommonNoun, userID) {
const data = {
age: childAge,
name: childName,
commonNoun: childCommonNoun,
};
const childCreationResponse = await API.graphql({
query: createChild,
variables: { input: data },
authMode: "AMAZON_COGNITO_USER_POOLS"
}).then(response => {
console.log(response);
return response;
}).catch(e => {
console.log(e);
return null;
});
return(childCreationResponse);
}
我已经尝试创建一个单独的函数来将已经创建的 Child 传递给 UserUpdate,但我似乎做对了。执行以下代码时出现此错误:“变量输入包含未为输入对象类型‘UpdateUserInput’定义的字段名称‘children’”
export async function addChildtoUserInDB(userID, userEmail, childData) {
const data = {
id: userID,
email: "Sparky", // this was for testing; works fine if this line exists but no line below
children: [childData]
};
console.log(childData);
const updateUserResponse = await API.graphql({
query: updateUser,
variables: { input: data },
authMode: "AMAZON_COGNITO_USER_POOLS"
}).then(response => {
console.log(response);
return response;
}).catch(e => {
console.log("catch");
console.log(e);
return null;
});
return(updateUserResponse);
}
如果我注释掉关于“孩子”的那一行,代码就可以正常工作。我尝试过各种不同的东西;例如去掉括号和不同的格式,改成 Child,不同版本的this String solution,我也发现了这个input type thing,但感觉它与多个@hasMany table references 不兼容。
我还找到了 this solution 在引用父项的同时创建子项/叶项,但不确定如何调整它,因为最后一个代码示例“userToDoItemsOwner”中的语法似乎无处不在。
在这里欢迎任何想法;我感觉很困! :)
我想通了!我最终将我的架构稍微修改为以下内容,根据卢克的建议删除了@belongsTo:
type User @model @auth(rules: [{allow: owner}]) {
id: ID!
email: String! @index(name: "byEmail", queryField: "userByEmail", sortKeyFields: ["id"])
children: [Child] @hasMany
settings: String
lastInteraction: String
}
type Child @model @auth(rules: [{allow: owner}]) {
id: ID!
name: String!
age: String!
commonNoun: String!
stories: [Story] @hasMany
}
type Story @model @auth(rules: [{allow: owner}]) {
id: ID!
status: String
storyType: String
storyData: String!
}
正确的模式是在使用“userChildrenId”引用用户 ID 的同时创建子项目。这是与拥有用户项目关联的子对象的创建代码:
async function createChildinDB(childAge, childName, childCommonNoun, userID) {
const data = {
age: childAge,
name: childName,
commonNoun: childCommonNoun,
userChildrenId: userID
};
const childCreationResponse = await API.graphql({
query: createChild,
variables: { input: data },
authMode: "AMAZON_COGNITO_USER_POOLS"
}).then(response => {
return response;
}).catch(e => {
console.log(e);
return null;
});
return(childCreationResponse);
}
有了这个模式,我仍然能够成功查询与特定用户关联的所有孩子:
export async function getChildrenforUser(userID) {
// filter on only children of user
const variablesForChildrenofUserQuery = {
filter: {
userChildrenId: {
eq: userID
}
}
}
const getUserChildren = await API.graphql({
query: listChildren,
variables: variablesForChildrenofUserQuery,
authMode: "AMAZON_COGNITO_USER_POOLS"
}).then(response => {
console.log(response);
return response;
}).catch(e => {
console.log(e);
return null;
});
return(getUserChildren);
}
希望这对将来的其他人有帮助:)