Which Category is your question related to?
API
What AWS Services are you utilizing?
AppSync
Provide additional details e.g. code snippets
When should I use @connection
as opposed to @key
? It seems to me I can do many-to-many or one-to-many relationship using both directives. Is @key
meant to replace @connection
? Or would there be a specific use case where @connection
might be more useful? I tried looking up documentation and issues and @mikeparisstuff said in https://github.com/aws-amplify/amplify-cli/issues/1406#issuecomment-494533788:
The
@connection
directive will then go through some sort of deprecation and re-introduction process.
Does that mean we should ditch @connection
now that @key
is introduced?
Hey @calspre, the @connection
directive will not be going away, but we are considering a new directive that enables many of the same use cases but is built upon @key
. The @connection
directive abstracts away the underlying index configuration and indexes cannot be changed in significant ways after being created. This abstraction led to confusion and errors when trying to change a @connection's
fields or arguments. Using @key
provides more hands on control of the table and will be the recommended way of configuring indexes moving forward and we have updated the documentation to recommend a pattern where you introduce new indexes before removing old ones to avoid update issues related to GSIs.
Thanks @mikeparisstuff for the response.
Using
@key
provides more hands on control of the table and will be the recommended way of configuring indexes moving forward [...]
Is it safe to assume that @connection
will be there for backward compatibility but @key
will be a more flexible, recommended way for index configuration (since you are considering a new directive that's built on @key
)?
[...] and we have updated the documentation to recommend a pattern where you introduce new indexes before removing old ones to avoid update issues related to GSIs.
Are you referring to this section?
If @key
is a recommended way, is there a way to delete existing @connection
and somehow migrate to @key
directive? I am a little scared to touch @connection
due to the known CloudFormation issues and if there's a certain procedure to migrate like the link above, I am happy to follow.
@calspre Yes @connection
will remain for backwards compatible reasons and the intention is to provide a new mechanism the achieves the same goal but that allows you to change the @connection
after the fact (even though you still will not be able to change index structures after the fact and should follow the create a new index before deleting an old index process).
It is possible to replace a @connection
with a @key
but should be done carefully. Here is one method you can use to move towards @key
.
Given this schema:
type Post @model {
id: ID!
title: String
comments: [Comment] @connection(name: "PostComments")
}
type Comment @model {
id: ID!
content: String
post: Post @connection(name: "PostComments")
}
If you look at build/stacks/Comment.json
, you will see the CommentTable with the following GSI definition:
"GlobalSecondaryIndexes": [
{
"IndexName": "gsi-PostComments",
"KeySchema": [
{
"AttributeName": "commentPostId",
"KeyType": "HASH"
}
],
"Projection": {
"ProjectionType": "ALL"
},
"ProvisionedThroughput": {
...
}
}
]
To can replace the @connection
with the @key
by adding:
type Post @model {
id: ID!
title: String
comments: [Comment]
}
type Comment @model @key(name: "gsi-PostComments", fields: ["commentPostId"], queryField: "commentsByPost") {
id: ID!
content: String
post: Post
}
You need to make sure the names match and the order of the attributes included in the key schema match that of the "fields" argument.
Note: DynamoDB has the restriction that you cannot change a GSI & cannot remove and create a GSI in the same CFN update.
One disclaimer is that until the new directive you will lose the Post.comments
& Comment.post
resolvers but will gain a Query.commentsByPost
resolver that achieves a similar result. If you want to make sure that the migration is doing what you think, you can compare the values of build/stacks/Comment.json
before and after the change.
Thanks @mikeparisstuff! That sounds reasonable. I will give it a try.
@calspre Closing this issue for now, please feel free to comment on this thread if you still have any queries around this.
@mikeparisstuff Is there any documentation to use a key instead of connection from scratch? I tried the example above and got the error that the commentPostId field didn't exist.
@mikeparisstuff Is there any documentation to use a key instead of connection from scratch? I tried the example above and got the error that the commentPostId field didn't exist.
Yes just read the docs it clearly shows how you should create the keys you're using in your @key
transformer in your graphQL schema. I haven't tested this yet but in the case of migrating the fact that your table already has that field setup through @connection
is probably why you can omit it. Again I haven't tested this so I don't know if you can actually omit it or was this just a shorthand demo.
@amirmishani The docs does not say anything about using @key instead of @connection, it only shows how to use @key and query it with a single table
When will this new @key
be made available?
jeez this @key stuff is strange especially when the @connection does all the work for you. Just need a quick solution for sorting values.
@connection lets you reverse query the parent field, @key would require you to write your own resolvers to achieve the same function. If I am not mistaken there isn't any additional cost involved with that resolver right? Then isn't @connection a really good feature to maintain. If you choose not to use reverse mapping ever, you can go with implementing only @key with name,fields. Or will you be adding reverse query as an option under @key? Then there would be no use for @connection
@mikeparisstuff I changed all @connection to @key due to this post but now I noticed that my non-scalar are not automatically added to the filters.
For example:
type Ad @model @key(name: "adsByUser", fields: ["userID"]) {
id: ID
userID: String!
publishedAt: AWSDateTime!
price: Float!
location: Location!
}
type Location {
district: Int!
county: Int
parish: Int
}
The filters are automatically added for publishedAt or price but not for location. Any idea what I'm doing wrong?
Most helpful comment
jeez this @key stuff is strange especially when the @connection does all the work for you. Just need a quick solution for sorting values.