Open Tedsterh opened 2 years ago
The zip file is still in the pull request.
Also, I believe more changes will be needed in the lambda resolver, to handle an index. We will want to Query
it, for one.
Oh, I just realised what you're doing. You're not trying to add a count for secondary indexes like I thought (?). So the query stuff is not relevant.
Yes sorry, I'm just creating a count field for list connections, I thought I had remove the .zip so i'll go back and do that now.
I think we can get the name of the index generated by @hasMany
so that we can scan the index rather than filter it, not sure which would be more efficient?
Or we could force an index
field so that we don't have to try and find it ourselves, like they do on the @hasMany
if you want to use your own index.
Hmm I have to admit I've never actually used @hasMany
. Can you show me an example schema for one? We should use the index if it generates one.
You can use it with a custom index or let it generate one, both do the same thing effectively I'm just not sure how we could easy access the generated one from our directive.
type Post @model {
id: ID!
title: String!
comments: [Comment] @hasMany
}
type Comment @model {
id: ID!
content: String!
}
Or with a custom index:
type Post @model {
id: ID!
title: String!
comments: [Comment] @hasMany(indexName: "byPost", fields: ["id"])
}
type Comment @model {
id: ID!
postID: ID! @index(name: "byPost", sortKeyFields: ["content"])
content: String!
}
We could then require them to pass the index name which in this case is byPost
So at a high level, you want to be able to getPost(id: 35){ commentCount }
, which will give you the number of associated comments?
For @hasMany
, I think we will want to always use a Dynamo Query
for these kinds of requests, since they are always associated with an index. It will certainly be much faster. A good way to check what kind of Dynamo call we should use it to look at the resolvers generated by Amplify for Post{ comments }
. We will broadly want to replicate this, only inside the lambda, and using the COUNT
attribute.
Yes that's what I'm thinking, the hope is because we are querying it directly too I can use a filter on it, to filter out certain comments from a total in this case.
I'll look at using an index then and checkout their resolvers for the query, I've not used dynamo queries before.
Should I make a new handler or just edit the current one to accept an optional index name?
Definitely use the same handler. Most of the code will remain the same and we don't want to duplicate everything. You can pass the info like the index name in through a new key in the event (alongside context
, tableName
etc).
Yeah so dynamo's Query
can do everything Scan
can do, including applying arbitrary filters. But there's the restriction that you can only Query
one partition, not the entire table. But we can just copy what Amplify does, like I said.
This is how they do it for the posts one they have a postID
passed into the query that they can access
#if( !$util.isNull($ctx.args. postID) )
#set( $modelQueryExpression.expression = "#postID = : postID" )
#set( $modelQueryExpression.expressionNames = {
"#postID": "postID"
} )
#set( $modelQueryExpression.expressionValues = {
": postID": {
"S": "$ctx.args. postID"
}
} )
do you know what's in the context, is there a way to access the primary key of the model that the field is in?
I have found out how to use the indexes we simply pass in the index name IndexName: event.indexName
, and then it uses the expressionNames and expressionValues to do the actual filtering.
Okay, so you'll have to write a resolver for the @hasMany
fields that passes this info into the lambda. Check out the AppSync docs for resolvers, they're quite helpful: https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html. But if there's anything you aren't able to do with them, we can push it to the lambda.
According to the docs we should be able to do something like ctx.source.id
so we could either figure out the name of the primary key in the generate stuff or we could just have an argument passed into the directive again, I think the primary key would be better?
What I would suggest is actually checking for the existence of the @hasMany
directive, and if it's present, extracting out the index information from that, possibly using some functions from the relational transformer module. I don't think AppSync inherently knows what the primary key is for a table, and even if it did, it may not be the index the user selected.
I have added a new direct called
fieldCount
that uses anhasMany
ormanyToMany
directive to access the other table instead, it also has a field argument like these connections so you can pass a field for it to return on, if none are provided it generates one similar to thehasOne
directive.I am not too sure how the resolvers work so not sure if it maps to the field properly or not just yet, any help and tips would be amazing!