Description
When using template-based GSI keys (both PK and SK), upsert, patch, and update operations do not write the GSI key attributes (gsiN1pk, gsiN1sk) to the DynamoDB item. Only create and put (which use PutItem internally) correctly write these attributes.
Reproduction
Entity definition
export const ArticleLikeEntity = new Entity(
{
model: {
entity: 'articleLike',
version: '1',
service: 'media',
},
attributes: {
articleId: {
type: 'string',
required: true,
},
likeCount: {
type: 'number',
required: true,
default: 0,
},
},
indexes: {
byArticleId: {
pk: {
field: 'pk',
composite: ['articleId'],
},
sk: {
field: 'sk',
composite: [],
},
},
likeRanking: {
index: 'gsiN1',
pk: {
field: 'gsiN1pk',
composite: [],
template: 'ARTICLE_LIKE',
},
sk: {
field: 'gsiN1sk',
composite: ['likeCount'],
template: '${likeCount}',
},
},
},
},
{ client: dynamoClient, table: tableName }
);
Steps to reproduce
1. Using upsert (GSI keys NOT written):
await ArticleLikeEntity.upsert({ articleId: 'test-article' })
.add({ likeCount: 1 })
.go();
Result: Item is created with likeCount: 1, but gsiN1pk and gsiN1sk are missing from the record.
2. Using create (GSI keys ARE written):
await ArticleLikeEntity.create({
articleId: 'test-article',
likeCount: 1,
}).go();
Result: Item is created with likeCount: 1, gsiN1pk: "article_like", and gsiN1sk: 1. GSI keys are correctly populated.
3. Using patch after create (GSI SK not updated):
// After create with likeCount: 1
await ArticleLikeEntity.patch({ articleId: 'test-article' })
.add({ likeCount: 1 })
.go();
Result: likeCount is incremented to 2, but gsiN1sk remains 1 (not updated to 2).
Expected behavior
upsert should write GSI template-based key attributes.
patch/update should re-compute and update GSI template-based SK when the underlying attribute changes.
Actual behavior
upsert does not include GSI template-based keys in the UpdateExpression.
patch/update updates the underlying attribute but does not re-compute the GSI SK from the template.
Root cause analysis
Looking at the source code:
create/put use PutItem, which includes updatedKeys (containing GSI attributes) directly in the Item — works correctly.
upsert/patch/update use UpdateItem with UpdateExpression. The GSI key re-computation from templates appears to be missing from the expression builder for these operations.
This seems related to previously fixed issues (#343, #366, #412) but specifically affects the template-based key pattern with Number-typed SK.
Environment
- ElectroDB: v3.7.5
- AWS SDK: v3
- DynamoDB Local: latest
- Node.js: v24.1.0
Workaround
Use put (PutItem) instead of patch/upsert for mutations that affect GSI template-based keys:
const existing = await ArticleLikeEntity.get({ articleId }).go();
const newCount = (existing.data?.likeCount ?? 0) + 1;
await ArticleLikeEntity.put({ articleId, likeCount: newCount }).go();
Description
When using
template-based GSI keys (both PK and SK),upsert,patch, andupdateoperations do not write the GSI key attributes (gsiN1pk,gsiN1sk) to the DynamoDB item. Onlycreateandput(which usePutIteminternally) correctly write these attributes.Reproduction
Entity definition
Steps to reproduce
1. Using
upsert(GSI keys NOT written):Result: Item is created with
likeCount: 1, butgsiN1pkandgsiN1skare missing from the record.2. Using
create(GSI keys ARE written):Result: Item is created with
likeCount: 1,gsiN1pk: "article_like", andgsiN1sk: 1. GSI keys are correctly populated.3. Using
patchaftercreate(GSI SK not updated):Result:
likeCountis incremented to 2, butgsiN1skremains 1 (not updated to 2).Expected behavior
upsertshould write GSI template-based key attributes.patch/updateshould re-compute and update GSI template-based SK when the underlying attribute changes.Actual behavior
upsertdoes not include GSI template-based keys in theUpdateExpression.patch/updateupdates the underlying attribute but does not re-compute the GSI SK from the template.Root cause analysis
Looking at the source code:
create/putusePutItem, which includesupdatedKeys(containing GSI attributes) directly in theItem— works correctly.upsert/patch/updateuseUpdateItemwithUpdateExpression. The GSI key re-computation from templates appears to be missing from the expression builder for these operations.This seems related to previously fixed issues (#343, #366, #412) but specifically affects the
template-based key pattern with Number-typed SK.Environment
Workaround
Use
put(PutItem) instead ofpatch/upsertfor mutations that affect GSI template-based keys: