Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/directory/directory.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ export const directory = {
},
{
path: 'src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-http-datasource/index.mdx'
},
{
path: 'src/pages/[platform]/build-a-backend/data/custom-business-logic/batch-ddb-operations/index.mdx'
}
]
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { getCustomStaticPath } from '@/utils/getCustomStaticPath';

export const meta = {
title: 'Batch DynamoDB Operations',
description:
'Batch DynamoDB Operations',
platforms: [
'android',
'angular',
'flutter',
'javascript',
'nextjs',
'react',
'react-native',
'swift',
'vue'
]
};

export const getStaticPaths = async () => {
return getCustomStaticPath(meta.platforms);
};

export function getStaticProps() {
return {
props: {
meta
}
};
}

Batch DynamoDB operations allow you to add multiple items in single mutation.

## Step 1 - Define a custom mutation

```ts title="amplify/data/resource.ts"
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';

const schema = a.schema({
// 1. Define your return type as a custom type or model
Post: a.model({
id: a.id(),
content: a.string(),
likes: a.integer()
}),

// 2. Define your mutation with the return type and, optionally, arguments
BatchCreatePost: a
.mutation()
// arguments that this query accepts
.arguments({
content: a.string().array()
})
.returns(a.ref('Post').array())
// only allow signed-in users to call this API
.authorization(allow => [allow.authenticated()])
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
schema
});
```

## Step 2 - Configure custom business logic handler code

After your query or mutation is defined, you need to author your custom business logic using a [custom resolver powered by AppSync JavaScript resolver](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html).

Custom resolvers work on a "request/response" basis. You choose a data source, map your request to the data source's input parameters, and then map the data source's response back to the query/mutation's return type. Custom resolvers provide the benefit of no cold starts, less infrastructure to manage, and no additional charge for Lambda function invocations. Review [Choosing between custom resolver and function](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html#choosing-data-source).

In your `amplify/data/resource.ts` file, define a custom handler using `a.handler.custom`.

```ts title="amplify/data/resource.ts"
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';

const schema = a.schema({
Post: a.model({
id: a.id(),
content: a.string(),
likes: a.integer()
}),

BatchCreatePost: a
.mutation()
.arguments({
contents: a.string().array()
})
.returns(a.ref('Post').array())
.authorization(allow => [allow.authenticated()])
// 1. Add the custom handler
.handler(
a.handler.custom({
dataSource: a.ref('Post'),
entry: './BatchCreatePostHandler.js',
})
)
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
schema
});
```

Amplify will store some values in the resolver context stash that can be accessed in the custom resolver.

| Name | Description |
| ------------------------- | -------------------------------------------- |
| awsAppsyncApiId | The ID of the AppSync API. |
| amplifyApiEnvironmentName | The Amplify api environment name. (`NONE` in sandbox) |

The Amplify generated DynamoDB table names can be constructed from the variables in the context stash. The table name is in the format `<model-name>-<aws-appsync-api-id>-<amplify-api-environment-name>`. For example, the table name for the `Post` model would be `Post-123456-dev` where `123456` is the AppSync API ID and `dev` is the Amplify API environment name.

```ts title="amplify/data/BatchCreatePostHandler.js"
import { util } from '@aws-appsync/utils';

export function request(ctx) {
var now = util.time.nowISO8601();

return {
operation: 'BatchPutItem',
tables: {
[`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyApiEnvironmentName}`]: ctx.args.contents.map((content) =>
util.dynamodb.toMapValues({
content,
id: util.autoId(),
createdAt: now,
updatedAt: now,
})
),
},
};
}

export function response(ctx) {
if (ctx.error) {
util.error(ctx.error.message, ctx.error.type);
}
return ctx.result.data[`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyApiEnvironmentName}`];
}
```

## Step 3 - Invoke the custom query or mutation

From your generated Data client, you can find all your custom queries and mutations under the `client.queries.` and `client.mutations.` APIs respectively.

```ts
const { data, errors } = await client.mutations.BatchCreatePost({
contents: ['Post 1', 'Post 2', 'Post 3']
});
```
Loading