更新嵌套地图dynamodb

时间:2018-08-18 19:28:55

标签: python nested amazon-dynamodb boto3

我有一个带有包含嵌套地图的属性的dynamodb表,我想更新一个特定的库存项目,该项目通过一个过滤器表达式进行过滤,从而从该地图中生成单个项目。

如何编写一个更新表达式以将其名称更新为name = opel的项目的“到位三”,标签包括“ x1”(可能还有f3)? 这应该只更新第一个列表元素的location属性。

memcpy

3 个答案:

答案 0 :(得分:6)

更新的答案-基于更新的问题陈述

您可以使用update expressions更新嵌套地图中的属性,以便仅更新项目的一部分(即DynamoDB将对您的项目应用补丁的等效项),但是,因为DynamoDB是文档数据库,所有操作(输入,获取,更新,删除等)对整个项目都起作用。

因此,在您的示例中,假设User是分区键,并且没有排序键(在该示例中我没有看到任何可能是排序键的属性),那么更新请求可能看起来像这样:

table.update_item(
  Key={
    'User': 'test'
  },
  UpdateExpression="SET #inv[0].#loc = :locVal",
  ExpressionAttributeNames={
    '#inv': 'inventory',
    '#loc': 'location'
  },
  ExpressionAttributeValues={
    ':lovVal': 'in place three',
  },
)

也就是说,您必须知道项目架构的外观以及应该正确更新项目中的哪些属性。

DynamoDB无法对子项目进行操作。意思是,没有办法告诉Dynamo执行诸如“更新项目之类的操作,设置具有'name'等于'opel'的属性的'inventory'数组元素的'location'属性。 / em>

这可能不是您想要的答案,但是今天已经可以使用了。通过稍微更改架构,您也许可以更接近所需。

如果您需要按名称引用子项,则可以存储以下内容:

{
  "inventory": {
    "opel": {
       "location": "in place one",      # I want to update this
       "tags": [ "x1", "f3" ]
    },
    "abc": {
       "location": "in place two",
       "tags": [ "a3", "f5" ]
    }
  },
  "User" :"test" 
} 

那么您的查询将是:

table.update_item(
  Key={
    'User': 'test'
  },
  UpdateExpression="SET #inv.#n.#loc = :locVal",
  ExpressionAttributeNames={
    '#inv': 'inventory',
    '#loc': 'location',
    '#n': 'opel'
  },
  ExpressionAttributeValues={
    ':lovVal': 'in place three',
  },
)

但是YMMV还是有局限性的,因为您只能按名称识别库存物品(即,您仍然不能说“使用标签'x1'更新库存”

最终,您应该仔细考虑为什么需要Dynamo来为您执行这些复杂的操作,而不是具体说明要更新的内容。

答案 1 :(得分:0)

您可以按以下方式更新嵌套地图:

  1. 首先创建并清空 map 类型的 item属性。在示例中,图形是空项目属性。

    dynamoTable = dynamodb.Table('abc')
            dynamoTable.put_item(
                Item={
                    'email': email_add,
                    'graph': {},
                }
    
    1. 如下更新嵌套地图。

>

brand_name ='opel'
DynamoTable = dynamodb.Table('abc')
     dynamoTable.update_item(
            Key={
            'email': email_add,
            },
            UpdateExpression="set #Graph.#brand= :name, ",
            ExpressionAttributeNames={
                '#Graph': 'inventory',
                '#brand': str(brand_name),
            },
            ExpressionAttributeValues = {
                    ':name': {
                            "location": "in place two",
                            'tag': {
                                'graph_type':'a3',
                                'graph_title': 'f5'
                        } }

答案 2 :(得分:0)

更新Mike的答案,因为这种方式不再起作用了(至少对我而言)。

现在这样工作(注意UpdateExpressionExpressionAttributeNames):

table.update_item(
  Key={
    'User': 'test'
  },
  UpdateExpression="SET inv.#brand.loc = :locVal",
  ExpressionAttributeNames={
    '#brand': 'opel'
  },
  ExpressionAttributeValues={
    ':locVal': 'in place three',
  },
)

无论Key={}中有什么内容,它始终是分区键(和排序键,如果有的话)。

编辑: 似乎这种方式仅适用于2级嵌套属性。在这种情况下,您只能将“ ExpressionAttributeNames”用于“中间”属性(在本示例中,该属性为#brandinv.#brand.loc)。我现在还不确定什么是真正的规则。