Amazon dynamodb 是否可以在DynamoDB中向上插入嵌套字段?

Amazon dynamodb 是否可以在DynamoDB中向上插入嵌套字段?,amazon-dynamodb,upsert,Amazon Dynamodb,Upsert,我想在DynamoDB中“插入”一个文档。也就是说,我想指定一个键和一组字段/值对。如果不存在具有该键的文档,我希望使用该键和我指定的键/值对创建一个文档。如果存在具有该键的文档,我希望将我指定的字段设置为指定的值(如果这些字段以前不存在,则应添加它们)。现有文档上的任何其他未指定字段都应保留 当我设置的字段/值对都是顶级字段时,我似乎可以很好地处理这个调用。如果我有嵌套结构,UpdateItem将用于设置嵌套字段,只要该结构存在。换句话说,如果我的现有文档有“foo”:{},那么我可以成功设置

我想在DynamoDB中“插入”一个文档。也就是说,我想指定一个键和一组字段/值对。如果不存在具有该键的文档,我希望使用该键和我指定的键/值对创建一个文档。如果存在具有该键的文档,我希望将我指定的字段设置为指定的值(如果这些字段以前不存在,则应添加它们)。现有文档上的任何其他未指定字段都应保留

当我设置的字段/值对都是顶级字段时,我似乎可以很好地处理这个调用。如果我有嵌套结构,
UpdateItem
将用于设置嵌套字段,只要该结构存在。换句话说,如果我的现有文档有
“foo”:{}
,那么我可以成功设置
“foo.bar”:42

但是,如果已经没有
foo
对象,我似乎无法设置
“foo.bar”:42
(比如在没有指定字段的文档的情况下,我的“upsert”表现为“insert”)

几年前我在AWS论坛上发现,这似乎意味着我想做的事情做不到,但我希望这一点最近有所改变,或者有人知道怎么做

UpdateItem
的行为类似于“upsert”操作:如果表中存在该项,则更新该项,如果不存在,则添加(插入)一个新项。

可以使用以下查询实现(“foo.bar”:42):

 table.update_item(Key = {'Id' : id},
              UpdateExpression = 'SET foo = :value1',
              ExpressionAttributeValues = {':value1': {'bar' : 42}}
              )

希望这有帮助:)

我发现这个更新项限制(顶级属性与嵌套属性)也令人沮丧。最终我找到了这个答案,并且能够解决这个问题:

它需要两个UpdateItem调用(可能更多,具体取决于嵌套级别?)。我只需要一个关卡,所以我就是这样做的:

  • 使用属性_exists条件更新该项,以便在顶层属性尚不存在时将其创建为空映射。如果整个项丢失,或者该项存在并且具有其他您不希望丢失的预先存在的属性,则此操作将起作用

  • 然后执行第二级更新项以更新嵌套值。只要父对象存在(例如,在我的例子中是一个空映射),它就工作得很好

  • 我得到的印象是您没有使用python,但下面是python代码,用于在如下项中完成嵌套属性的向上插入:

    {
      "partition_key": "key",
      "top_level_attribute": {
        "nested_attribute": "value"
      }
    }
    
    python代码:

    def upsert_nested_item(self, partition_key, top_level_attribute_name, nested_attribute_name, nested_item_value):
        try:
            self.table.update_item(
                Key={'partition_key': partition_key},
                ExpressionAttributeNames={f'#{top_level_attribute_name}': top_level_attribute_name},
                ExpressionAttributeValues={':empty': {}},
                ConditionExpression=f'attribute_not_exists(#{top_level_attribute_name})',
                UpdateExpression=f'SET #{top_level_attribute_name} = :empty',
            )
        except self.DYNAMODB.meta.client.exceptions.ConditionalCheckFailedException:
            pass
        self.table.update_item(
            Key={'partition_key': partition_key},
            ExpressionAttributeNames={
                f'#{top_level_attribute_name}': top_level_attribute_name,
                f'#{nested_attribute_name}': nested_attribute_name
            },
            ExpressionAttributeValues={f':{top_level_attribute_name}': nested_item_value},
            UpdateExpression=f'SET #{top_level_attribute_name}.#{nested_attribute_name} = :{top_level_attribute_name}',
        )
    

    为了给你另一个数据点,我在2015年5月(ish)研究了这个问题,你提到的同样的问题仍然存在。我无法实现嵌套字段upsert的目标,因此我必须改变解决该问题的方法以及存储数据的方式。@mkobit感谢您的数据点;这也是我得出的结论。因为我的数据有固定数量的嵌套层,所以我最终将其存储为扁平的,带有名为
    foo\u bar
    的字段,并且我将编组/解编组代码添加到我的DAO层以对其进行翻译。这是一种痛苦,但在一年后的同一个问题上,它似乎运作得足够好(至少到目前为止)。恼人的是,Dynamo没有抛出错误,只是没有保存数据树的那部分。有人找到解决方案了吗?请在这里发帖。是的,我读过。但是如果你读了我的问题,我无法插入嵌套对象。我将它与嵌套对象一起使用,它工作正常(w/DynamoDBMapper)。但是,如果
    foo
    的初始值除了您正在更新的
    bar
    值之外还有其他键,它们不会丢失吗?例如,如果初始值是
    {foo:{biz:33,bar:0}}
    ,并且您只想更改
    foo.bar
    ,而保持
    foo
    对象的其余部分不变,那么这是否可行?我已经回答了一个类似的问题。如果有效,请检查并评论。