DynamoDB - 如何使用 updateItem 更新嵌套对象

Posted

技术标签:

【中文标题】DynamoDB - 如何使用 updateItem 更新嵌套对象【英文标题】:DynamoDB - How to upsert nested objects with updateItem 【发布时间】:2021-12-24 15:08:55 【问题描述】:

您好,我是 dynamoDB 的新手。下面是发电机表的架构


   "user_id":1, // partition key
   "dob":"1991-09-12", // sort key 
   "movies_watched":
      "1":
         "movie_name":"twilight",
         "movie_released_year":"1990",
         "movie_genre":"action"
      ,
      "2":
         "movie_name":"harry potter",
         "movie_released_year":"1996",
         "movie_genre":"action"
      ,
      "3":
         "movie_name":"lalaland",
         "movie_released_year":"1998",
         "movie_genre":"action"
      ,
      "4":
         "movie_name":"serendipity",
         "movie_released_year":"1999",
         "movie_genre":"action"
      
   
..... 6 more attributes


如果项目(带有 dob 的用户 ID)不存在,我想插入一个新项目,否则通过检查电影是否尚不可用 movies_watched 地图将电影添加到现有的 movies_watched 地图。

目前,我正在尝试使用update(params) 方法。

以下是我的方法:

function getInsertQuery (item) 
  const exp = 
    UpdateExpression: 'set',
    ExpressionAttributeNames: ,
    ExpressionAttributeValues: 
  
  Object.entries(item).forEach(([key, item]) => 
    if (key !== 'user_id' && key !== 'dob' && key !== 'movies_watched') 
      exp.UpdateExpression += ` #$key = :$key,`
      exp.ExpressionAttributeNames[`#$key`] = key
      exp.ExpressionAttributeValues[`:$key`] = item
    
  )

  let i = 0
  Object.entries(item. movies_watched).forEach(([key, item]) => 
    exp.UpdateExpression += ` movies_watched.#uniqueID$i = :uniqueID$i,`
    exp.ExpressionAttributeNames[`#uniqueID$i`] = key
    exp.ExpressionAttributeValues[`:uniqueID$i`] = item
    i++
  )
  exp.UpdateExpression = exp.UpdateExpression.slice(0, -1)
  return exp

上述方法只是为所有***属性以及嵌套属性(带有文档路径)创建具有表达式名称和值的更新表达式。

如果该项目已经通过更新movies_watched 地图可用,则效果很好。但是如果该项目不可用并且在插入时抛出异常。以下是例外:

The document path provided in the update expression is invalid for update

但是,我仍然不确定如何在 movies_watched 地图中检查重复的电影

有人可以指导我正确的方向吗,非常感谢任何帮助!

提前致谢

【问题讨论】:

【参考方案1】:

根据您的模型,如果在更新之前不从 DDB 读取项目,则无法执行此操作(此时该过程很简单)。如果您不想将这种额外的读取容量强加到您的表上以进行更新,那么您需要重新设计您的数据模型:

    您可以将 movies_watched 更改为 Set 并保存对电影的引用。需要注意的是,Set 只能包含数字或字符串,因此您将拥有电影 ID 或名称,或者将数据保留为您的 Set 中的 JSON 字符串,然后在读取时将其解析回 JSON。使用 SET,您可以对 movies_watched 属性执行 ADD 操作。 https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html#Expressions.UpdateExpressions.ADD

    您可以采用单表设计方法,并使用(PK:userId 和 SK:movie_id)将这些电影作为单独的项目观看。要获取用户,您将执行查询并仅指定 PK=userId -> 您将获得一个集合,其中一个项目是您的用户记录,其他项目是 movies_watched。如果您是 DynamoDB 的新手并且正在学习其中的技巧,那么我建议您采用这种方法。 https://www.alexdebrie.com/posts/dynamodb-single-table/

【讨论】:

以上是关于DynamoDB - 如何使用 updateItem 更新嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AWS Lambda 按名称查询 dynamoDB 表

DynamoDB 如何使用 AWS KMS

AWS SDK JavaScript v3 / 如何在 dynamoDB 扫描命令中使用 ExpressionAttributeNames?

如何将Amazon SQS与Dynamodb集成

如何使用 nodejs 使用 Dynamodb 并行扫描检索数据

如何在 Lambda 中使用 python 从 dynamoDB 获取/获取某些列?