Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add batch ddb operations page #8145

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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,152 @@
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
dpilch marked this conversation as resolved.
Show resolved Hide resolved
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).

palpatim marked this conversation as resolved.
Show resolved Hide resolved
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())
dpilch marked this conversation as resolved.
Show resolved Hide resolved
.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
});
```
palpatim marked this conversation as resolved.
Show resolved Hide resolved

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. |
| amplifyBranchName | The Amplify branch 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-branch-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 branch name.

```ts title="amplify/data/BatchCreatePostHandler.js"
import { util } from '@aws-appsync/utils';
export function request(ctx) {
dpilch marked this conversation as resolved.
Show resolved Hide resolved
var now = util.time.nowISO8601();

return {
operation: "BatchPutItem",
tables: {
[`Post-${ctx.stash.awsAppsyncApiId}-${ctx.stash.amplifyBranchName}`]: 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.amplifyBranchName}`];
}
```

## 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