tywalch/electrodb

Incorrect validation using partition key as sort key in GSI

Opened this issue · 1 comments

Describe the bug
I have an error I'm getting which I don't quite understand. I have the following dynamoDB with a GSI and a primary index. I try to represent this in electrodb with the following setup:

indexes: {
        asset: {
            pk: {
                field: "assetId",
                composite: ["assetId"]
            }
        },
        listingToAssets: {
            index: "listingToAssets",
            pk: {
                field: "listingId",
                composite: ["listingId"]
            },
            sk: {
                field: "assetId",
                composite: ["assetId"]
            }
        }
    }

I get the following error though:
Runtime.UnhandledPromiseRejection: ElectroError: The Sort Key (sk) on Access Pattern 'listingToAssets' references the field 'listingId' which is already referenced by the Access Pattern(s) 'asset' as a Partition Key. Fields mapped to Partition Keys cannot be also mapped to Sort Keys. - For more detail on this error reference: https://github.com/tywalch/electrodb#inconsistent-index-definition

Entity/Service Definitions
Include your entity model (or a model that sufficiently recreates your issue) to help troubleshoot.

{
    model: {
        entity: "assetId",
        version: "1",
        service: "task"
    },
    attributes: {
        assetId: {
            type: "string",
            default: () => uuid(),
        },
        listingId: {
            type: "string",
            required: true
        },
        status: {
            type: "string",
            required: true
        },
        type: {
            type: "string",
            required: true,
        },
        createdAt:{
            type: "number",
            required: true
        },
        updatedAt: {
            type: "number",
            required: true
        },
        ttl: {
            type: "number",
            required: true
        }
    },
    indexes: {
        asset: {
            pk: {
                field: "assetId",
                composite: ["assetId"]
            }
        },
        listingToAssets: {
            index: "listingToAssets",
            pk: {
                field: "listingId",
                composite: ["listingId"]
            },
            sk: {
                field: "assetId",
                composite: ["assetId"]
            }
        }
    }

Expected behavior
No validation error. GSI shouldn't have validations for what's in the primary index.

Errors

Runtime.UnhandledPromiseRejection: ElectroError: The Sort Key (sk) on Access Pattern 'listingToAssets' references the field 'listingId' which is already referenced by the Access Pattern(s) 'asset' as a Partition Key. Fields mapped to Partition Keys cannot be also mapped to Sort Keys. - For more detail on this error reference: https://github.com/tywalch/electrodb#inconsistent-index-definition 

Additional context
Discord discussion link:
https://discord.com/channels/983865673656705025/994984119224246303/1041444793349329078

I'm having a similar issue. In my case I already have a create table with an inverted-key index which just inverts partition key and sort key.

const teamUsers = new Entity({
  model: {
    entity: "TeamUser",
    service: "SSO",
    version: "1",
  },
  attributes: {
    teamId: {
      type: "string",
      required: true,
    },
    userId: {
      type: "string",
      required: true,
    },
    teamName: {
      type: "string",
      required: true,
    },
    workspaceId: {
      type: "string",
      required: true,
    },
  },
  indexes: {
    table: {
      pk: {
        field: "partitionKey",
        template: "TEAM#${teamId}",
        casing: "none",
        composite: ["teamId"],
      },
      sk: {
        field: "sortKey",
        template: "USER#${userId}",
        casing: "none",
        composite: ["userId"],
      },
    },
    inverted: {
      index: "inverted-key",
      pk: {
        field: "sortKey",
        template: "USER#${userId}",
        casing: "none",
        composite: ["userId"],
      },
      sk: {
        field: "partitionKey",
        template: "TEAM#${teamId}",
        casing: "none",
        composite: ["teamId"],
      },
    },
  },
});

ElectroDB Playground reproduction

The Sort Key (sk) on Access Pattern 'inverted' references the field 'sortKey' which is already referenced by the Access Pattern(s) 'table' as a Partition Key. Fields mapped to Partition Keys cannot be also mapped to Sort Keys.

I really needed this error not to be thrown to be able to use ElectroDB, because all DynamoDB tables we have in our company follows that inverted-key pattern.