sensedeep / dynamodb-onetable

DynamoDB access and management for one table designs with NodeJS
https://doc.onetable.io/
MIT License
689 stars 109 forks source link

queryItems requires { hidden:true } to support groupByType for AWS SDK v3 #527

Closed robpott closed 7 months ago

robpott commented 7 months ago

The hidden parameter is required for queryItems to support groupByType when using AWS SDK V3. AWS SDK V2 does NOT require the hidden parameter.

debug.ts

/*
    debug.ts - Just for debug

    Edit your test case here and invoke via: "jest debug"

    Or run VS Code in the top level directory and just run.
 */
import {AWS, Client, Entity, Match, Model, Table, print, dump, delay} from './utils/init'
import {OneSchema} from '../src/index.js'

jest.setTimeout(7200 * 1000)

//  Change with your schema
const schema = {
    version: '0.0.1',
    indexes: {
        primary: {hash: 'pk', sort: 'sk'},
        gs1: {hash: 'gs1pk', sort: 'gs1sk', project: 'all'},
    },
    params: {
        createdField: 'createdAt',
        updatedField: 'updatedAt',
        isoDates: true,
        timestamps: true,
    },
    models: {
        User: {
            pk: {type: String, value: '${_type}#${email}'},
            sk: {type: String, value: '${_type}#'},
            email: {type: String, required: true},
        },
    } as const,
}

//  Change your table params as required
const table = new Table({
    name: 'DebugTable',
    client: Client,
    partial: false,
    schema,
    logger: true,
})

//  This will create a local table
test('Create Table', async () => {
    if (!(await table.exists())) {
        await table.createTable()
        expect(await table.exists()).toBe(true)
    }

    let User = table.getModel('User')

    let user = await User.create({
        email: 'user@example.com',
    })
})

test('items are grouped when hidden:true', async () => {
    let items = await table.queryItems({pk: 'User#user@example.com'}, {hidden: true})
    let collection = table.groupByType(items)
    expect(collection.User.length).toBe(1)
})

test('items are grouped when hidden is NOT defined', async () => {
    let items = await table.queryItems({pk: 'User#user@example.com'})
    let collection = table.groupByType(items)
    expect(collection.User.length).toBe(1)
})

test('Destroy Table', async () => {
    await table.deleteTable('DeleteTableForever')
    expect(await table.exists()).toBe(false)
})

When running with AWS SDK V3 below is the failure

 FAIL  test/debug.ts (8.379 s)
  ● items are grouped when hidden:true

    TypeError: Cannot read properties of undefined (reading 'length')

      59 |     let items = await table.queryItems({pk: 'User#user@example.com'}, {hidden: true})
      60 |     let collection = table.groupByType(items)
    > 61 |     expect(collection.User.length).toBe(1)
         |                            ^
      62 | })
      63 |
      64 | test('items are grouped when hidden is NOT defined', async () => {

      at Object.<anonymous> (test/debug.ts:61:28)

  ● items are grouped when hidden is NOT defined

    TypeError: Cannot read properties of undefined (reading 'length')

      65 |     let items = await table.queryItems({pk: 'User#user@example.com'})
      66 |     let collection = table.groupByType(items)
    > 67 |     expect(collection.User.length).toBe(1)
         |                            ^
      68 | })
      69 |
      70 | test('Destroy Table', async () => {

      at Object.<anonymous> (test/debug.ts:67:28)

Expected behavior When using AWS SDK V3 the hidden parameter should NOT be required

Environment (please complete the following information):

mobsense commented 7 months ago

Thanks for the report and test case.

I'm getting different results.

So net/net

Use {hidden: true} AND if you use queryItems, you need {parse: true}

robpott commented 7 months ago

Thanks for getting back to me. In this case we need to use queryItems to search only on PK so it's an edge case.

What results do you get for those test cases with aws adk V2 and V3? I do NOT need {parse: true} for the test to pass for either aws adk V2 or V3, just need to pass {hidden: true} on for SDK v3 to pass

mobsense commented 7 months ago

In V2, you don't need parse: true because the underlying DocumentClient from the AWS v2 sdk does the parsing back to javascript. But safe, and recommended to use for both.

robpott commented 7 months ago

Thank you for information!