From f9b6a8a705717f0ec0b96750b83e0f534f3ec11c Mon Sep 17 00:00:00 2001 From: Chris Bonifacio Date: Wed, 27 Mar 2024 12:47:24 -0400 Subject: [PATCH 1/4] edits to custom business logic --- .../data/custom-business-logic/index.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx b/src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx index 86bde5a8188..575b7f9a467 100644 --- a/src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx +++ b/src/pages/gen2/build-a-backend/data/custom-business-logic/index.mdx @@ -112,8 +112,8 @@ After your query or mutation is defined, you need to author your custom business In your `amplify/data/echo-handler/` folder, create a `handler.ts` file. You can import a utility type for your function handler via the `Schema` type from your backend resource. This gives you type-safe handler parameters and return values. -```ts title="amplify/data/echo-handler.ts" -import type { Schema } from './resource' +```ts title="amplify/data/echo-handler/handler.ts" +import type { Schema } from '../resource' export const handler: Schema["echo"]["functionHandler"] = async (event, context) => { const start = performance.now(); @@ -170,7 +170,7 @@ export const data = defineData({ -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). +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`. @@ -227,12 +227,12 @@ export function request(ctx) { } } -export function response(ctx: Context) { +export function response(ctx) { return ctx.result } ``` -By default, you'll be able to access any existing database tables (powered by Amazon DynamoDB) using `a.ref('MODEL_NAME')`. But you can also reference any other external data source from within your AWS account, by adding them to your backend definition. +By default, you'll be able to access any existing database tables (powered by Amazon DynamoDB) using `a.ref('MODEL_NAME')`. But you can also reference any other external data source from within your AWS account, by adding them to your backend definition. The supported data sources are: - Amazon DynamoDB @@ -314,7 +314,7 @@ export const data = defineData({ -The `.handler()` accepts an array of handlers that will run in a pipeline. For now, in the developer preview, you can only use `a.handler.custom()` and `a.handler.function()`. All other handlers, such as `a.handler.inlineSql()` are under active development. +The `.handler()` accepts an array of handlers that will run in a pipeline. For now, in the developer preview, you can only use `a.handler.custom()` and `a.handler.function()`. All other handlers, such as `a.handler.inlineSql()` are under active development. From 53245f27027c19db96c88f8df6aea66f61104606 Mon Sep 17 00:00:00 2001 From: Chris Bonifacio Date: Mon, 8 Apr 2024 13:20:24 -0400 Subject: [PATCH 2/4] update secondary index code examples --- .../data-modeling/secondary-index/index.mdx | 127 ++++++++++-------- 1 file changed, 68 insertions(+), 59 deletions(-) diff --git a/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx b/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx index 7e6e2da61dc..d957bad4443 100644 --- a/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx +++ b/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx @@ -14,20 +14,20 @@ export function getStaticProps(context) { You can optimize your list queries based on "secondary indexes". For example, if you have a **Customer** model, you can query based on the customer's **id** identifier field by default but you can add a secondary index based on the **accountRepresentativeId** to get list customers for a given account representative. -A secondary index consists of a "hash key" and, optionally, a "sort key". Use the "hash key" to perform strict equality and the "sort key" for greater than (gt), greater than or equal to (ge), less than (lt), less than or equal to (le), equals (eq), begins with, and between operations. +A secondary index consists of a "hash key" and, optionally, a "sort key". Use the "hash key" to perform strict equality and the "sort key" for greater than (gt), greater than or equal to (ge), less than (lt), less than or equal to (le), equals (eq), begins with, and between operations. ```ts export const schema = a.schema({ - Customer: a.model({ - name: a.string(), - phoneNumber: a.phone(), - accountRepresentativeId: a.id().required() - // highlight-start - }).secondaryIndexes([ - a.index('accountRepresentativeId') - ]) - // highlight-end - .authorization([a.allow.public()]), + Customer: a + .model({ + name: a.string(), + phoneNumber: a.phone(), + accountRepresentativeId: a.id().required(), + }) + // highlight-start + .secondaryIndexes((index) => [index("accountRepresentativeId")]) + // highlight-end + .authorization([a.allow.public()]), }); ``` @@ -39,19 +39,17 @@ import { generateClient } from 'aws-amplify/data'; const client = generateClient(); -const { - data, - errors +const { data, errors } = // highlight-start -} = await client.models.Customer.listByAccountRepresentativeId({ - accountRepresentativeId: "YOUR_REP_ID" -}); - // highlight-end + await client.models.Customer.listByAccountRepresentativeId({ + accountRepresentativeId: "YOUR_REP_ID", + }); +// highlight-end ``` -Amplify uses Amazon DynamoDB tables as the default data source for `a.model()`. For key-value databases, it is critical to model your access patterns with "secondary indexes". Use the `.index()` modifier to configure a secondary index. +Amplify uses Amazon DynamoDB tables as the default data source for `a.model()`. For key-value databases, it is critical to model your access patterns with "secondary indexes". Use the `.index()` modifier to configure a secondary index. **Amazon DynamoDB** is a key-value and document database that delivers single-digit millisecond performance at any scale but making it work for your access patterns requires a bit of forethought. DynamoDB query operations may use at most two attributes to efficiently query data. The first query argument passed to a query (the hash key) must use strict equality and the second attribute (the sort key) may use gt, ge, lt, le, eq, beginsWith, and between. DynamoDB can effectively implement a wide variety of access patterns that are powerful enough for the majority of applications. @@ -59,20 +57,23 @@ Amplify uses Amazon DynamoDB tables as the default data source for `a.model()`. ## Add sort keys to secondary indexes -You can define "sort keys" to add a set of flexible filters to your query, such as "greater than" (gt), "greater than or equal to" (ge), "less than" (lt), "less than or equal to" (le), "equals" (eq), "begins with" (beginsWith), and "between" operations. +You can define "sort keys" to add a set of flexible filters to your query, such as "greater than" (gt), "greater than or equal to" (ge), "less than" (lt), "less than or equal to" (le), "equals" (eq), "begins with" (beginsWith), and "between" operations. ```ts title="amplify/data/resource.ts" -const schema = a.schema({ - Customer: a.model({ - name: a.string(), - phoneNumber: a.phone().required(), - accountRepresentativeId: a.id().required(), - }).secondaryIndexes([ - a.index('accountRepresentativeId') - // highlight-next-line - .sortKeys(["name"]), - ]) -}).authorization([a.allow.owner()]); +export const schema = a.schema({ + Customer: a + .model({ + name: a.string(), + phoneNumber: a.phone(), + accountRepresentativeId: a.id().required(), + }) + .secondaryIndexes((index) => [ + index("accountRepresentativeId") + // highlight-next-line + .sortKeys(["name"]), + ]) + .authorization([a.allow.owner()]), +}); ``` On the client side, you should find a new `listBy...` query that's named after hash key and sort keys. For example, in this case: `listByAccountRepresentativeIdAndName`. You can supply the filter as part of this new list query: @@ -81,13 +82,14 @@ On the client side, you should find a new `listBy...` query that's named after h const { data, errors - // highlight-next-line -} = await client.models.Customer.listByAccountRepresentativeIdAndName({ - accountRepresentativeId: 'YOUR_REP_ID', - name: { - beginsWith: 'Rene', - }, -}); +} = +// highlight-next-line + await client.models.Customer.listByAccountRepresentativeIdAndName({ + accountRepresentativeId: 'YOUR_REP_ID', + name: { + beginsWith: 'Rene', + }, + }); ``` ## Customize the query field for secondary indexes @@ -96,16 +98,19 @@ You can also customize the auto-generated query name under `client.models. [ + index("accountRepresentativeId") + // highlight-next-line + .queryField("listByRep"), + ]) + .authorization([a.allow.owner()]), +}); ``` In your client app code, you'll see query updated under the Data client: @@ -125,15 +130,19 @@ const { To customize the underlying DynamoDB's index name, you can optionally provide the `name()` modifier. ```ts -const schema = a.schema({ - Customer: a.model({ - name: a.string(), - phoneNumber: a.phone(), - accountRepresentativeId: a.id().required(), - }).secondaryIndexes([ - a.index('accountRepresentativeId') - // highlight-next-line - .name("MyCustomIndexName"), - ]) -}).authorization([a.allow.owner()]); +const schema = a + .schema({ + Customer: a + .model({ + name: a.string(), + phoneNumber: a.phone(), + accountRepresentativeId: a.id().required(), + }) + .secondaryIndexes((index) => [ + index("accountRepresentativeId") + // highlight-next-line + .name("MyCustomIndexName"), + ]), + }) + .authorization([a.allow.owner()]); ``` From 3364772d1ba3f9b56d93b69a7da0972483dc310d Mon Sep 17 00:00:00 2001 From: Chris Bonifacio Date: Fri, 12 Apr 2024 09:34:01 -0400 Subject: [PATCH 3/4] Update index.mdx --- .../data/data-modeling/secondary-index/index.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx b/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx index f17daa4d3ed..2b5771fa309 100644 --- a/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx +++ b/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx @@ -141,7 +141,7 @@ const schema = a index("accountRepresentativeId") // highlight-next-line .name("MyCustomIndexName"), - ]), - }) - .authorization([a.allow.owner()]); + ]) + .authorization([a.allow.owner()]) + }); ``` From ea78a8ce0550509fb022e3bd347cf602224b013e Mon Sep 17 00:00:00 2001 From: Chris Bonifacio Date: Fri, 12 Apr 2024 09:51:37 -0400 Subject: [PATCH 4/4] Update index.mdx --- .../data-modeling/secondary-index/index.mdx | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx b/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx index 2b5771fa309..b37f89c14e8 100644 --- a/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx +++ b/src/pages/gen2/build-a-backend/data/data-modeling/secondary-index/index.mdx @@ -16,7 +16,7 @@ You can optimize your list queries based on "secondary indexes". For example, if A secondary index consists of a "hash key" and, optionally, a "sort key". Use the "hash key" to perform strict equality and the "sort key" for greater than (gt), greater than or equal to (ge), less than (lt), less than or equal to (le), equals (eq), begins with, and between operations. -```ts +```ts title="amplify/data/resource.ts" export const schema = a.schema({ Customer: a .model({ @@ -32,7 +32,7 @@ export const schema = a.schema({ The example client query below allows you to query for "Customer" records based on their `accountRepresentativeId`: -```ts +```ts title="src/App.tsx" import { type Schema } from '../amplify/data/resource'; import { generateClient } from 'aws-amplify/data'; @@ -77,7 +77,7 @@ export const schema = a.schema({ On the client side, you should find a new `listBy...` query that's named after hash key and sort keys. For example, in this case: `listByAccountRepresentativeIdAndName`. You can supply the filter as part of this new list query: -```ts +```ts title="src/App.tsx" const { data, errors @@ -114,7 +114,7 @@ const schema = a.schema({ In your client app code, you'll see query updated under the Data client: -```ts +```ts title="src/App.tsx" const { data, errors @@ -128,20 +128,19 @@ const { To customize the underlying DynamoDB's index name, you can optionally provide the `name()` modifier. -```ts -const schema = a - .schema({ - Customer: a - .model({ - name: a.string(), - phoneNumber: a.phone(), - accountRepresentativeId: a.id().required(), - }) - .secondaryIndexes((index) => [ - index("accountRepresentativeId") - // highlight-next-line - .name("MyCustomIndexName"), - ]) - .authorization([a.allow.owner()]) - }); +```ts title="amplify/data/resource.ts" +const schema = a.schema({ + Customer: a + .model({ + name: a.string(), + phoneNumber: a.phone(), + accountRepresentativeId: a.id().required(), + }) + .secondaryIndexes((index) => [ + index("accountRepresentativeId") + // highlight-next-line + .name("MyCustomIndexName"), + ]) + .authorization([a.allow.owner()]), +}); ```