dynamodb-toolbox icon indicating copy to clipboard operation
dynamodb-toolbox copied to clipboard

Check why primary/secondary GSIs are using if_not_exists

Open kr1p70n1c opened this issue 1 year ago • 6 comments

Is this still a thing with the latest version, i.e. by default you get generated UpdateExpression like this:

SET #gsi1pk = if_not_exists(#gsi1pk,:gsi1pk), #gsi1sk = if_not_exists(#gsi1sk,:gsi1sk)

I am having this issue with v0.3.5, and am wondering if this has been addressed in the latest version, where it is straight forward to not have it generated like that, and where you do not have to provide the whole UpdateExpression yourself either.

Sidenote: I have seen in an issue where they say this is not an issue and the array for composite keys fixes this, but this won't work for me (besides, I've read in latest documentation that the array for composite keys is going to be dropped in the future).

For now I am bypassing this issue by providing the UpdateExpression in the params object to the query method, i.e. instead of having this in the expression (which was generated):

... #gsi1sk = if_not_exists(#gsi1sk,:gsi1sk) ...

I replace it with:

... #gsi1sk = :gsi1sk ...

Regards

kr1p70n1c avatar Jul 22 '22 01:07 kr1p70n1c

Hi @kr1p70n1c! The only way the if_not_exists should be generated is if you set a default for the attribute. Can you post your Table and Entity definitions?

jeremydaly avatar Jul 22 '22 10:07 jeremydaly

Hi @jeremydaly,

Thank you for your quick response.

I certainly do have a default defined:

        gsi1sk: {
            hidden: false,
            type: 'string',
            default: (data: any) => {
                return data.status && data.id ? `ORDERSTATUS#${data.status}#${data.id}` : null;
            }
        },

I have to update that sort key as it is part of my modeling as I am using the mutable status as part of an access pattern:

  • Get user orders by status

As stated before, I do have it working for now as I am specifying the whole UpdateExpression, I was just hoping that there would have been an easier way to indicate/override that certain fields should not have the if_not_exists auto-generated in an UpdateExpression.

kr1p70n1c avatar Jul 22 '22 11:07 kr1p70n1c

Ah, I see. The point of the if_not_exists for default values is so that when an UpdateItem is called without specifying the value, it'll send the default value in to ensure that newly created items have a default value. This way, if an item exists, then the default value won't overwrite the existing attribute value in the item.

It looks like you want to set the value (meaning not use the default functionality) when updating an item. In that case, you should use the transform property when defining your Entity (see here: https://www.dynamodbtoolbox.com/docs/entity#using-an-object). This will allow you to send the result in as the VALUE, not the DEFAULT. If you return undefined from the transform function, then the default behavior should kick in.

jeremydaly avatar Jul 22 '22 14:07 jeremydaly

@jeremydaly Ah thanks for the feedback. Just to confirm the version of the library, must I use the latest for this to work or will v0.3.5 do?

I am asking because I am still on v0.3.5 and I have implemented the transform function as well, and returning the value from it (and I can confirm that value is indeed the new value I need it to be), but the UpdateExpression still generates as:

... #gsi1sk = if_not_exists(#gsi1sk,:gsi1sk) ...

As reference my default and transform functions:

            default: (data: any) => {
                return data.status && data.id ? `ORDERSTATUS#${data.status}#${data.id}` : null;
            },
            transform: (value: any, data: any) => {
                logger.info('gsi1sk - value, data:', value, data);
                return value;
            }

Do note if I return undefined from transform then my items are created with the gsi1sk field being empty.

kr1p70n1c avatar Jul 22 '22 16:07 kr1p70n1c

Hmm, that's not the way it should work. Check v0.4.X of the library to see if there is a change in behavior, but that shouldn't have been touched. I'll mark this as a bug and make sure it gets addressed.

jeremydaly avatar Jul 22 '22 17:07 jeremydaly

I tried the latest version (0.4.3) again now, but I still have the issue as I reported in #269

I made an additional comment their now.

kr1p70n1c avatar Jul 23 '22 10:07 kr1p70n1c