I am currently experiencing an issue with #belongsTo in connection with #auth when more than one sortKey is inside of the parent element.
The following error comes up when I try to amplify push the schema:
🛑 Invalid #belongsTo on Comments:todo. Provided fields do not match the size of primary key(s) for Todos
Below schema should reproduce the error:
type Todos #model #auth(rules: [{ allow: public }]) {
id: ID!
createdAt: String
number: Int
title: String
description: String
comments: [Comments] #hasMany(indexName: "byComments", fields: ["id"])
baseType: String
#index(
name: "byNumber"
queryField: "todosByNumber"
sortKeyFields: ["number"]
)
#index(
name: "byTitle"
queryField: "todosByTitle"
sortKeyFields: ["title"]
)
#index(
name: "byDescription"
queryField: "todosByDescription"
sortKeyFields: ["description"]
)
}
type Comments #model #auth(rules: [{ allow: public }]) {
id: ID!
todosID: ID! #index(name: "byComments")
todo: Todos #belongsTo(fields: ["todosID"])
createdAt: String
firstName: String
lastName: String
messageID: ID #index(name: "commentsByMessages")
message: Messages #belongsTo(fields: "messageID")
}
type Messages #model #auth(rules: [{ allow: public }]) {
id: ID!
title: String
content: String
comments: [Comments] #hasMany(indexName: "byComments", fields: ["id"])
}
Does anyone have a solution on how to setup #belongsTo and #auth correctly?
Looking forward to your help!
Related
HI i am sharing my schema please provide suggestion. Whenever i open content page i got this error like sync error occured in this model.
type Message #model #auth(rules: [{allow: public}]) {
id: ID!
content: String!
userID: ID! #index(name: "byUser")
chatroomID: ID
}
type ChatRoom #model #auth(rules: [{allow: public}]) {
id: ID!
newMessages: Int
LastMessage: Message #hasOne
Messages: Message #hasOne
ChatRoomUsers: [User] #manyToMany(relationName: "ChatRoomUser")
}
type User #model #auth(rules: [{allow: public}]) {
id: ID!
name: String!
status: String
imageUri: String
Messages: [Message] #hasMany(indexName: "byUser", fields: ["id"])
chatrooms: [ChatRoom] #manyToMany(relationName: "ChatRoomUser")
}
I have chatRooms and each chatRoom has two chatRoomUsers and they can exchange messages between each other in this chatRoom, every time when user is creating a message, we are updating chatRoom's updatedAt, so I could have track of which chatRoom was updated last and the last message that was typed there, so basically I always want to know the updatedAt field for each chat.
Every chatRoomUsers has a profile_id which is unique and every profile_id might have chatRoomUsers since he can be a participants of many chatrooms. So I am trying to get all chatrooms that belong to certain profile_id sorted by updatedAt field (which shows the time when chatRoom was updated) in either ASC or DESC order. I've been using following schema to achieve that but it did not work. So I am trying to run getProfile query with certain profile_id as an argument, which could give me a list of chatRooms for this particular profile_id in the order that I want. AWS generates that ability for me, based on my schema but it is not working, can anyone help with that?
Example of getProfile function:
getProfile(profile_id: "201") {
createdAt
lastName
name
profile_id
updatedAt
chatRooms(sortDirection: ASC) {
items {
chatRoomID
createdAt
id
profileID
updatedAt
}
}
}
Schema:
type Profile #model #auth(rules: [{ allow: public }]) {
profile_id: ID! #primaryKey
name: String!
lastName: String
avatarLink: String
chatRooms: [ChatRoom] #manyToMany(relationName: "ProfileChats")
updatedAt: AWSDateTime
createdAt: AWSDateTime
}
type ChatRoom #model #auth(rules: [{ allow: public }]) {
id: ID! #index(sortKeyFields: ["updatedAt"])
updatedAt: AWSDateTime!
createdAt: AWSDateTime
profiles: [Profile] #manyToMany(relationName: "ProfileChats")
messages: [Message] #hasMany(indexName: "byChatRoom", fields: ["id"])
lastMessageID: ID!
lastMessage: Message #hasOne(fields: ["lastMessageID"])
}
type Message #model #auth(rules: [{ allow: public }]) {
id: ID!
content: String!
profileID: ID!
chatRoomID: ID!
#index(
name: "byChatRoom"
sortKeyFields: ["createdAt"]
queryField: "messagesByChatRoom"
)
profile: Profile #hasOne(fields: ["profileID"])
updatedAt: AWSDateTime
createdAt: AWSDateTime
I am constructing a React Native app with AWS Amplify, AppSync, Cognito, Dynamodb and GraphQL.
I designed the schema.graphql file and want to push that to the cloud (amplify push).
Initially, it had no problem pushing to the cloud.
But as soon as I introduced #key and #connection , I get an error when pushing to cloud.
amplify push
The error is:
🛑 An error occurred during the push operation: Your GraphQL Schema is using
"#connection", "#key" directives from an older version of the GraphQL Transformer.
Visit https://docs.amplify.aws/cli/migration/transformer-migration/ to
learn how to migrate your GraphQL schema.
I read the article and followed their instruction to the best of my ability.
Then I get this error when pushing:
🛑 An error occurred during the push operation: Schema validation failed.
Unknown argument "keyName" on directive "#hasMany". Did you mean "indexName"?
GraphQL request:13:44
12 |
13 | portfolioCoins: [PortfolioCoin] #hasMany(keyName: "byUser", fields: ["id"])
| ^
14 | }
Directive "primaryKey" may not be used on OBJECT.
GraphQL request:16:27
15 |
16 | type PortfolioCoin #model #primaryKey(name: "byUser", fields: ["userId"]) {
| ^
17 | id: ID!
Unknown argument "name" on directive "#primaryKey".
GraphQL request:16:39
15 |
16 | type PortfolioCoin #model #primaryKey(name: "byUser", fields: ["userId"]) {
| ^
17 | id: ID!
Unknown argument "fields" on directive "#primaryKey".
GraphQL request:16:55
15 |
16 | type PortfolioCoin #model #primaryKey(name: "byUser", fields: ["userId"]) {
| ^
17 | id: ID!
Unknown argument "fields" on directive "#manyToMany".
GraphQL request:21:26
20 | userId: ID!
21 | user: User #manyToMany(fields: ["userId"])
| ^
22 |
Directive "#manyToMany" argument "relationName" of type "String!" is required, but it was not provided.
GraphQL request:21:14
20 | userId: ID!
21 | user: User #manyToMany(fields: ["userId"])
| ^
22 |
Unknown argument "fields" on directive "#manyToMany".
GraphQL request:24:26
23 | coinId: ID!
24 | coin: Coin #manyToMany(fields: ["coinId"])
| ^
25 | }
Directive "#manyToMany" argument "relationName" of type "String!" is required, but it was not provided.
GraphQL request:24:14
23 | coinId: ID!
24 | coin: Coin #manyToMany(fields: ["coinId"])
| ^
25 | }
This is my schema.graphql file:
# This "input" configures a global authorization rule to enable public access to
# all models in this schema. Learn more about authorization rules here: https://docs.amplify.aws/cli/graphql/authorization-rules
# input AMPLIFY {
# globalAuthRule: AuthRule = { allow: public }
# } # FOR TESTING ONLY!
type User #model #auth(rules: [{ allow: public }]) {
id: ID!
email: String!
name: String
image: String
networth: Float!
portfolioCoins: [PortfolioCoin] #connection(keyName: "byUser", fields: ["id"])
}
type PortfolioCoin #model #key(name: "byUser", fields: ["userId"]) {
id: ID!
amount: Float!
userId: ID!
user: User #connection(fields: ["userId"])
coinId: ID!
coin: Coin #connection(fields: ["coinId"])
}
type Coin #model {
id: ID!
cgId: String!
name: String!
symbol: String!
image: String
currentPrice: Float!
valueChange24H: Float!
valueChange1D: Float!
valueChange7D: Float!
priceHistoryString: String
}
And here is an image of the table relationships for your reference:
Please tell me how I can replace the #key and #connection properly so that I can amplify push successfully. Your help will be extremely appreciated.
I encountered this a while back when GraphQL Transformer version 2 came out and my schema stopped working.
I found this article helpful to understand how the new keywords worked.
https://aws.amazon.com/blogs/mobile/aws-amplify-announces-the-new-graphql-transformer-v2-more-feature-rich-flexible-and-extensible/
This link is also very helpful for modeling in the current version: https://docs.amplify.aws/cli/graphql/data-modeling
I think your schema should probably work as follows in the current version:
type User #model #auth(rules: [{ allow: public }]) {
id: ID!
email: String!
name: String
image: String
networth: Float!
portfolioCoins: [PortfolioCoin] #hasMany
}
type PortfolioCoin #model #key(name: "byUser", fields: ["userId"]) {
id: ID!
amount: Float!
user: User #belongsTo
coin: Coin #hasOne
}
type Coin #model {
id: ID!
cgId: String!
name: String!
symbol: String!
image: String
currentPrice: Float!
valueChange24H: Float!
valueChange1D: Float!
valueChange7D: Float!
priceHistoryString: String
}
With the GraphQL Transformer v2, Amplify introduces as a range of new features to help customers create app backends even faster and easier.
The #key directive is being replaced by two new directives.
#primaryKey and #index
#connection is being replaced with several new directives.
#hasOne
#hasMany
#belongsTo
#manyToMany
for your case is #hasOne
read
https://docs.amplify.aws/cli/migration/transformer-migration/#changes-that-amplify-cli-will-auto-migrate-for-you
for more info on this.
Here's your code let me know if bugs arise.
type User #model #auth(rules: [{ allow: public }]) {
id: ID!
email: String!
name: String
image: String
networth: Float!
portfolioCoins: PortfolioCoin #hasOne(keyName: fields: ["id"])
}
type PortfolioCoin #model {
id: ID!
amount: Float!
userId: ID!#primaryKey #index(name:"byUser")
user: User #hasOne(fields: ["userId"])
coinId: ID!
coin: Coin #hasOne(fields: ["coinId"])
}
type Coin #model {
id: ID!
cgId: String!
name: String!
symbol: String!
image: String
currentPrice: Float!
valueChange24H: Float!
valueChange1D: Float!
valueChange7D: Float!
priceHistoryString: String
}
My issue is that I need to have a connection between two schema models where each links to an array of the other. The scenario here is I have multiple Location, each Location has multiple Staff. Each Staff can also have multiple Location that they are authorized at.
I don't see a way to do this in the documentation. Originally I have each Location with multiple Staff, but this limits each Staff to 1 Location. I'm toying with the idea of altLocationNames as an array of strings with each Staff, but this would require me to perform an extra query of all Staff or all Locations if the altLocationNames is needed.
Does anybody know a clever way to do this, or even just the best way for me to get all Staff at Location as well as all Locations for a specific Staff?
Schemas:
type Staff
#model
#auth(rules: [{ allow: private, provider: iam }, { allow: private, provider: userPools }])
#key(fields: ["email"])
#key(name: "byId", fields: ["id"], queryField: "listStaffsById")
#key(name: "byLocation", fields: ["locationName", "recordedAt"], queryField: "listStaffsByLocation")
#key(name: "byRole", fields: ["role", "recordedAt"], queryField: "listStaffsByRole")
#key(name: "byStatus", fields: ["status", "recordedAt"], queryField: "listStaffsByStatus") {
email: AWSEmail!
altEmails: [AWSEmail]
id: ID!
locationName: String!
location: Location #connection(fields: ["locationName"])
altLocationNames: [String]
firstName: String
lastName: String
role: StaffRole
status: StaffStatus
recordedAt: AWSDateTime!
createdAt: AWSDateTime!
updatedAt: AWSDateTime!
}
type Location
#model
#auth(rules: [{ allow: private, provider: iam }, { allow: private, provider: userPools }])
#key(fields: ["name"]) {
name: String!
subdomain: String
address: String
phone: String
email: AWSEmail
staff: [Staff] #connection(keyName: "byLocation", fields: ["name"])
createdAt: AWSDateTime!
updatedAt: AWSDateTime!
}
Can you create middle table between location and staff table and fetch via that table.
Example:
type Staff
#model {
id: ID!
name: String
locations: [StaffLocation] #connection(keyName: "staffLocationByStaffId", fields: ["id"])
}
type Location
#model {
id: ID!
name: String
staffs: [StaffLocation] #connection(keyName: "staffLocationByLocationId", fields: ["id"])
}
type StaffLocation
#key(name: "staffLocationByStaffId", fields: ["staffId"])
#key(name: "staffLocationByLocationId", fields: ["locationId"])
#model {
id: ID!
staffId: ID!
locationId: ID!
staff: Staff #connection(fields: ["staffId"])
location: Location #connection(fields: ["locationId"])
}
type StudentCourses
#model(queries: null)
#auth(rules: [{ allow: public }])
#key(name: "byStudent", fields: ["studentID", "courseID"])
#key(name: "byCourse", fields: ["courseID", "studentID"]) {
id: ID!
studentID: ID!
courseID: ID!
student: Student! #connection(fields: ["studentID"])
course: Course! #connection(fields: ["courseID"])
}
type Course
#model
#auth(rules: [{ allow: public }])
#key(name: "bySchool", fields: ["schoolID"]) {
id: ID!
courseName: String!
schoolID: ID!
students: [Student!] #connection(keyName: "byCourse", fields: ["id"])
}
type Student
#model
#auth(rules: [{ allow: public }])
#key(name: "bySchool", fields: ["schoolID"]) {
id: ID!
studentName: String
studentEmail: String
sisID: Int
schoolID: ID!
courses: [Course!] #connection(keyName: "byStudent", fields: ["id"])
}
I followed the steps in docs to create a many to many relationship between student and courses but i keep getting this error Key byCourse does not exist for model Student even thought i created a model to connect school and courses. Thanks in advance
You need to omit keyName from Course, since in Student model, you have list of courses, so you can't really have #key directive for that.
https://docs.amplify.aws/cli-legacy/graphql-transformer/connection/#many-to-many-connections
type Course
#model
#auth(rules: [{ allow: public }])
#key(name: "bySchool", fields: ["schoolID"]) {
id: ID!
courseName: String!
schoolID: ID!
students: [Student!] #connection(fields: ["id"])
}
Anyone who is upto V2 of Amplify, they can get guidance from this link
https://docs.amplify.aws/cli/graphql/data-modeling/#belongs-to-relationship
Updated Flow has the following changes
You need to add #manyToMany on both tables that are going to join
This will create a third table by itself and will add Queries and Mutations for it as well.