amplify-count-directive
v1.1.0
Published
AmplifyCountDirective provides the ability to count the number of items in your DynamoDB tables using Amplify.
Downloads
42
Readme
AmplifyCountDirective
AmplifyCountDirective provides the ability to count the number of items in your DynamoDB tables using Amplify.
Example
This package provides the @count
directive which can be used to annotate your models.
Let's say we use it in the following schema:
type Foo @count @model {
id: ID!
string_field: String
int_field: Int
float_field: Float
bool_field: Boolean
}
This will compile into:
type Query {
getFoo(id: ID!): Foo
listFoos(filter: ModelFooFilterInput, limit: Int, nextToken: String): ModelFooConnection
countFoo(filter: ModelFooFilterInput): Int
}
Finally you can query the number of items in your table using the same filters as you would use to list them:
{
countFoo(filter: {
and: {
bool_field: {eq: false},
float_field: {le: 1.5},
string_field: {contains: "bar"}
}
})
}
Usage
- Install this module using
npm install -g amplify-count-directive
- Include the transformer in your amplify application by editing your
amplify/backend/api/<API_NAME>/transform.conf.json
{ "Version": 5, "ElasticsearchWarning": true, "transformers": [ + "amplify-count-directive" ] }
- Add
@count
to your model:
-type Foo @model {
+type Foo @model @count {
id: ID!
string_field: String
int_field: Int
float_field: Float
bool_field: Boolean
}
- Deploy your application using
amplify push
- (Optional) Regenerate your JavaScript/TypeScript query templates using
amplify codegen
How it Works
AmplifyCountDirective provides a directive in exactly the same way that Amplify provides the @model
directive.
When Amplify finds this directive in your schema, it them does two things:
- Transforms your schema to add
countFoo
to yourQuery
type - Adds a resolver for
countFoo
, which has a Lambda data source
This Lambda resolver then uses Scan with Select: "COUNT"
to count all items in the table that match the filters you have provided.
Development
- Add Jest unit tests to
test/test.ts
tests, and execute them usingnpm test
- The
amplify
directory also includes a simple Amplify application that can be used as a test case. You canamplify push
from this directory in order to test it out.
FAQs
Are you sure Amplify doesn't already offer this capability?
Yep. Take a look at this long thread where users complain about this fact.
The count
and scannedCount
attributes returned when you listFoo
only apply to each page of data individually, so are not helpful.
You can use the @searchable
directive to obtain some aggregation capabilities, but it's not cheap and the cost scales very poorly.
How much will this add to my AWS bill?
Ideally nothing. The AppSync resolvers are totally free to run, and only the Lambda function might end up costing you. However this package only uses the smallest size lambda, so it's realistically going to be free. It does however fire a few calls off to the DynamoDB table, so this might end up costing you a few cents, if you pay on demand.
What if I want to count using a secondary index?
Currently AmplifyCountDirective doesn't have this capability, but it should be quite simple to implement. Please consider helping out with https://github.com/multimeric/AmplifyCountDirective/issues/1.
Do I have to install this globally?
No you don't, but it's recommended that you do, because the Amplify CLI itself needs to be installed globally.
You can just npm install amplify-count-directive
in the root directory of your application, and it should work.
However you run into some risks of the deployment breaking when it uses different copies (global and local) of the same libraries.
Refer to this GitHub issue for more information.
How fast is the count process?
It's noticeably slower than listing a single page of results, which is what you get when you query listFoo
.
This happens because countFoo
uses a Lambda function, which can take a few seconds to spin up.
In addition, it has to actually churn through all the data in the table, even though it's just counting it.
In theory this could be optimised using GSIs (indexes), but this hasn't yet been implemented.
I therefore recommend you fire off the count query ASAP when your app loads, and start showing the first page of table data even before the count has returned.
Why couldn't you use AppSync VTL resolvers to do this?
AppSync is strange.
VTL looks like a programming language, but it's really just a templating language, and it doesn't have the ability to call the AWS API directly.
Instead you have to return a query template which will run a single API call.
This means that it can't count the number of items in a table, because this requires multiple successive Scan
calls to the DynamoDB table.
This is a bit unfortunate, because VTL resolvers are much faster, but that's just the way it is.
Why didn't you nest the count resolver inside the listFoo query?
If you try to access listFoo{ count }
, it will fire off a resolver for listFoo
, which isn't actually needed when you are counting table entries, so this would be a waste.
This option is therefore more efficient.
How can I update this package?
- Update it using
npm install -g amplify-count-directive@latest
- Edit your schema by adding some whitespace somewhere. This will force Amplify to realise the API has changed.
- Run
amplify push
as usual
Can I help with this?
Sure! Please do. You can find the GitHub issues here. Please let me know if you want to work on one and I can assign it to you.