amplify-category-api
amplify-category-api copied to clipboard
How to add a local secondary index with amplify-cli and transformers v2?
The category is: amplify cli transformers v2
How to create a LSI on DynamoDB table creation? This code will generate a GSI "lsiLastName"
type User @model @auth(rules: [{allow: owner, identityClaim: "sub"}]) {
id: ID!
owner: String! @primaryKey(sortKeyFields: [“firstName"]) @index(name: “lsiLastName”, sortKeyFields: [“lastName"])
firstName: String
lastName: String
}
Amplify version 9.2.1
I have tried adding the LSI using amplify override api
but I get this error, and the LSI is never created.
error: An attribute referenced in a KeySchema element is not defined in AttributeDefinitions
// extend.ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';
import * as dynamodb from '@aws-cdk/aws-dynamodb';
const owner: dynamodb.CfnGlobalTable.KeySchemaProperty = {
attributeName: 'owner',
keyType: 'HASH',
};
const lastName: dynamodb.CfnGlobalTable.KeySchemaProperty = {
attributeName: 'lastName',
keyType: 'RANGE',
};
const projection: dynamodb.CfnGlobalTable.ProjectionProperty = {
projectionType: 'ALL'
}
export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
resources.models['User'].modelDDBTable.localSecondaryIndexes = [
{
indexName: 'lsiLastName',
keySchema: [owner, lastName],
projection
},
]
}
Using this schema:
# schema.graphql
type User @model @auth(rules: [{allow: owner, identityClaim: "sub"}]) {
id: ID!
owner: String! @primaryKey(sortKeyFields: ["firstName"])
firstName: String!
lastName: String
}
Hey @guy-a :wave: thanks for raising this and apologies for the delay! I think you have the right approach with the override. Using the following schema and override file I was able to change the GSI to an LSI
# schema.graphql
type User @model {
id: ID!
owner: String!
@primaryKey(sortKeyFields: ["firstName"])
@index(name: "byLastName", sortKeyFields: ["lastName"])
firstName: String!
lastName: String
}
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper'
export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
const gsi = resources.models['User'].modelDDBTable.globalSecondaryIndexes
resources.models['User'].modelDDBTable.localSecondaryIndexes = gsi
delete resources.models['User'].modelDDBTable.globalSecondaryIndexes
}
Thank you @josefaidt This is indeed working perfectly when first creating the api, but any later changes to the schema, same or different models, or just an empty line - will yield this error message:
Removing an LSI requires replacement of the underlying DynamoDB table.
This update will replace table(s) [UderTable]
ALL EXISTING DATA IN THESE TABLES WILL BE LOST!
If this is intended, rerun the command with '--allow-destructive-graphql-schema-updates'.
Running amplify push --allow-destructive-graphql-schema-updates will give these errors, and eventually rollback the update:
CREATE_FAILED SubscriptiononCreateUserauth0FunctionSubscriptiononCreateUserauth0FunctionAppSyncFunction26F2963D AWS::AppSync::FunctionConfiguration
CREATE_FAILED UserTable AWS::DynamoDB::Table Thu Sep 08 2022 Resource handler returned message: "Number of attributes in KeySchema does not exactly match number of attributes defined in AttributeDefinitions" (RequestToken: e93f324f-ebcf-4556-bf60-2f25f3f4317c, HandlerErrorCode: InvalidRequest)
⠸ Rolling back (3 of 2)🛑 An error occurred during the push operation: /
["Index: 1 State: {\"deploy\":\"waitingForDeployment\"} Message: Resource is not in the state stackUpdateComplete"]
Hey @guy-a apologies for the delay here. Are you still experiencing this issue?
Hi @josefaidt , I switched to GSIs for now so I haven't tried it since than. It would be useful to be able to easily use LSIs using Amplify in future tables and projects.