【问题标题】:Dynamoose model update with hash key使用哈希键更新 Dynamoose 模型
【发布时间】:2021-11-22 22:53:29
【问题描述】:

我正在尝试针对 dynamoose 模型执行更新。这是关于调用model.update的文档

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

key 可以是表示 hashKey 的字符串或包含 hashKeyrangeKey 的对象。

我的架构同时具有 散列键(分区键)和 范围键(排序键),如下所示:

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

我已经创建了一个这样的对象(带有固定的演示时间戳)

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

我希望能够通过像这样引用 id 属性来更新 status 属性:

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'

但两者都会导致显示的错误:

如果我知道时间戳,我可以传入完整的复合键,因此以下 起作用:

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

然而,这需要我保持时间戳并与 id 并存。

在我的例子中,ID 字段本身应该是唯一的,所以我不需要两者都创建键,但想将日期添加为范围键以便它可以排序。我应该只更新我的架构,以便只有一个哈希键吗?我在想那些说 "`key 可以是表示哈希键的字符串" 的文档会让我只传递 ID,但这会在编译时引发错误(在 typescript 中)。

有什么建议吗?

【问题讨论】:

  • 为什么需要 date 作为 rangeKey?
  • 嘿查理,我可能可以删除它。它可能只是从其他地方复制的意大利面。没有强大的用例。
  • 如果您有时间,请帮我一个忙,在 Dynamoose GitHub 存储库上创建一个问题以改进有关此问题的错误消息。提供您的示例代码,甚至提供此 SO 帖子的链接。想要在这里获得更详细的更好的错误消息。

标签: amazon-dynamodb dynamoose


【解决方案1】:

这里的解决方案是从date属性中删除rangeKey。

这是因为在 DynamoDB 中,每个文档/项目都必须有一个唯一的“键”。这可以是 hashKey 或 hashKey + rangeKey。

由于您提到您的 id 属性是唯一的,您可能只想使用 hashKey 作为键,这应该可以解决问题。

在您的示例中,可能有许多具有该 ID 的文档,因此 DynamoDB 不知道要更新哪个。

不要忘记这会导致您的表格发生变化,因此您可能必须删除并重新创建表格。但这应该可以解决您遇到的问题。

【讨论】:

  • 感谢@Charlie - 感谢图书馆和支持
【解决方案2】:

从逻辑上讲,没有什么比在同一个分区中插入超过 1 个条目(在您的情况下是唯一 ID)中阻止您。如果日期不同,您可以插入多个具有相同 ID 的项目。

因此,如果您想仅通过其分区键(实际上是唯一 ID)获取项目,则需要使用查询来检索该项目(而不是 GET),但返回签名将是一个集合的项目。如您所知,分区中只有一个项目,您可以取第一个项目,并指定限制为 1 以保存 RCU。

【讨论】:

  • 这只是因为有hashKeyrangeKey。因为 OP 提到 id 是唯一的,所以您可以删除 rangeKey 并且它会起作用。如果出于某种原因,OP 需要保留 rangeKey,那么这个答案是完全正确的。但是我想不出一个用例来说明为什么这是必要的。 hashKeyrangeKey 的基本目的确实要求拥有 hashKey,因为它是独一无二的。所以在这里删除rangeKey 是更好的解决方案。
  • 您是对的,但是可能存在您无法更改的旧表架构,无论出于何种原因。可能还有其他 LSI 和 GSI 使用该排序键。
【解决方案3】:
// create model
let model = dynamoose.model(
  "SampleStatus",
  {
    id: {
      type: String,
      hashKey: true,
      "index": {
         "name": "index_name",
         "rangeKey": "date",
      } 
    },
    date: {
      type: Date
    },
    status: String,
  });

你必须告诉模式 hashKey 和 range 是一个分区键。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    • 2021-01-13
    • 2016-12-26
    • 2019-05-19
    相关资源
    最近更新 更多