Dynamoose model update with hash key

2.3k views Asked by At

I'm trying to execute an update against a dynamoose model. Here's the docs on calling model.update

Model.update(key[, updateObj[, settings]],[ callback])

key can be a string representing the hashKey or an object containing the hashKey & rangeKey.

My schema has both a hash key (partition key) and range key (sort key) like this:

// create model
let model = dynamoose.model(
  "SampleStatus",
  {
    id: {
      type: String,
      hashKey: true,
    },
    date: {
      type: Date,
      rangeKey: true,
    },
    status: String,
  });

I've created an object like this (with a fixed timestamp for demoing)

let timestamp = 1606781220842; // Date.Now()
model.create({
  id: "1",
  date: new Date(timestamp),
  status: "pending",
});

I'd like to be able to update the status property by referencing just the id property like this:

model.update({id: "1"}, {status: "completed"})
// err: The provided key element does not match the schema

model.update("1", {status: "completed"})
// err: Argument of type 'string' is not assignable to parameter of type 'ObjectType'

But both result in the shown errors:

I can pass in the full composite key if I know the timestamp, so the following will work:

let timestamp = 1606781220842; // Date.Now()
model.update({ id: "1", date: timestamp }, { status: "completed" });

However, that requires me holding onto the timestamp and persisting alongside the id.

The ID field, in my case, should, by itself, be unique, so I don't need both to create a key, but wanted to add the date as a range key so it was sortable. Should I just update my schema so there's only a single hash key? I was thinking the docs that said a "`key can be a string representing the hashkey" would let me just pass in the ID, but that throws an error on compile (in typescript).

Any suggestions?

3

There are 3 answers

1
Charlie Fish On

The solution here is to remove the rangeKey from the date property.

This is because in DynamoDB every document/item must have a unique “key”. This can either be the hashKey or hashKey + rangeKey.

Since you mention that your id property is unique, you probably want to use just the hashKey as the key, which should fix the issue.

In your example there could have been many documents with that id, so DynamoDB wouldn’t know which to update.

Don’t forget that this causes changes to your table so you might have to delete and recreate the table. But that should fix the problem you are running into.

2
Derrops On

Logically there is nothing stopping you than inserting more than 1 entry into the same partition (in your case the unique id). You could insert more than one item with the same id, if it had a different date.

Therefore if you want to get an item by only its partition key, which is really a unique ID, you need to use a query to retrieve the item (as opposed to a GET), but the return signature will be a collection of items. As you know you only have one item in the partition, you can take the first item, and specify a limit of 1 to save RCU.

0
yakob abada On
// create model
let model = dynamoose.model(
  "SampleStatus",
  {
    id: {
      type: String,
      hashKey: true,
      "index": {
         "name": "index_name",
         "rangeKey": "date",
      } 
    },
    date: {
      type: Date
    },
    status: String,
  });

You have to tell the schema that hashKey and range are one partition key.

Ref: https://dynamoosejs.com/guide/Schema#index-boolean--object--array