0

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?

KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • Why do you need date to be the rangeKey? – Charlie Fish Dec 01 '20 at 04:03
  • Hey Charlie, I can probably remove it. It might just be copy pasta from elsewhere. Don't have a strong use case for it. – KyleMit Dec 01 '20 at 04:08
  • 1
    Do me a favor if you have time, create an issue on the Dynamoose GitHub repo to improve the error message around this. Give your example code and even a link to this SO post. Wanna get a better error message with more detail here. – Charlie Fish Dec 01 '20 at 04:31

3 Answers3

1

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.

Charlie Fish
  • 18,491
  • 19
  • 86
  • 179
0

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.

Derrops
  • 7,651
  • 5
  • 30
  • 60
  • This is only the case because there is a `hashKey` and `rangeKey`. Because the OP mentioned that `id` is unique, you can remove the `rangeKey` and it'll work. If for whatever reason the OP needs to keep `rangeKey`, this answer is totally correct. However I can't think of a use case for why that would be necessary. The foundational purpose for the `hashKey` and `rangeKey` really call for just having the `hashKey` since it's unique. So removing the `rangeKey` is the better solution here. – Charlie Fish Dec 04 '20 at 15:19
  • You are right, however there could be a legacy table schema you can't change for whatever the reason.There could be other LSIs & GSIs as well which do use that sort key. – Derrops Dec 06 '20 at 05:14
0
// 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

yakob abada
  • 1,101
  • 14
  • 20