【问题标题】:how to add an empty or data map in dynamodb?如何在 dynamodb 中添加空映射或数据映射?
【发布时间】:2016-02-23 05:42:24
【问题描述】:

我有这样的事情:

{
  Records:{}
}

我只想在这样的记录中添加数据:

{
  Id: 123,
  Records:{
    10001: { event : "item1" }
  }
}

我的第一次尝试:

var params = {
    TableName : "Records",
    Key : { Id : 123 },
    UpdateExpression: 'set Record.#k1.event = :v1',
    ExpressionAttributeNames: { '#k1' :  10001},
    ExpressionAttributeValues: { ':v1' : 'item1' }
};

因为 Record.10001 不存在,所以它给我错误:

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

"ADD" 仅支持 NUMBER 和 SET 类型,因此不适合我的情况。

我的第二次尝试(第一次尝试创建空地图):

var params = {
    TableName : "Records",
    Key : { Id : 123 },
    UpdateExpression: 'set Record.#k1 = {}',
    ExpressionAttributeNames: { '#k1' :  10001},
};

它失败了,因为我的语法可能不正确,而且我找不到如何为属性创建一个空映射。

所以我的问题是如何将结构化对象作为地图或空地图添加到现有项目,如上面的示例?

我可以轻松地从亚马逊 DynamoDB 数据管理页面修改数据,所以至少我知道有一种方法可以做到这一点。我只需要知道怎么做。

谢谢

【问题讨论】:

    标签: amazon-dynamodb


    【解决方案1】:

    我以某种方式成功地做到了:

    var params = {
        TableName: "Records",
        Key: { Id: 123 },
        UpdateExpression: 'set Records.#k1 = :v1',
        ExpressionAttributeNames: {'#k1': '10001',},
        ExpressionAttributeValues: {':v1': { event: 'Yay~' } }
    };
    

    你可以选择使用

        UpdateExpression: 'set Records.#k1 = if_not_exists( Records.#k1, :v1)',
    

    避免覆盖现有记录。

    【讨论】:

    • 我们可以嵌套if_not_exists吗?例如if_not_exists(if_not_exists(path, :value), :value)
    • 显然不是。我收到了这个错误:Operator or function requires a document path; operator or function: if_not_exists'
    【解决方案2】:

    我找到了解决我们遇到的错误的方法。

    try:
        table.update_item( 
              Key = {'Id' : id},
              UpdateExpression = 'SET Records.#key1.#key2 = :value1',
              ExpressionAttributeNames = {'#key1': '10001', '#key2' : 'event'},
              ExpressionAttributeValues = {':value1': 'singing'}
             )
    except:
        table.update_item( 
              Key = {'Id' : id},
              UpdateExpression = 'SET Records = :value1',
              ExpressionAttributeValues = {':value1': {'10001': {'event' : 'dance'}}}
              )
    

    当我们第一次尝试更新时,我们得到“更新表达式中提供的文档路径对更新无效”错误。由于没有嵌套的 JSON,将引发异常。

    此后,任何更新例如 Record.10002 都不会抛出异常。将执行 try 块中的更新函数。

    如果这是处理这种情况的正确方法,请对此发表评论。

    【讨论】:

    • 在没有特定例外的情况下使用except 是不好的做法。你最终可能会吞下你不打算的错误。最好只捕获ClientError 异常。
    【解决方案3】:

    摆脱此类问题的一种可能解决方案:您必须提前创建一个空对象并存在于数据库中。

    例如,

    1. 在您的对象生成期间(数据库中的原始创建):

      字段:{ }

    2. 更新此字段使用:

          TableName: ....,
          Key: {
              .....
          },
          UpdateExpression: 'set field.#mapKey = :v',
          ExpressionAttributeNames: {
              '#mapKey': myName
          },
          ExpressionAttributeValues: {
              ':v': myValue
          }
      

    【讨论】:

      【解决方案4】:

      这可以在 c# 中完成,如下所示。

      如果你有以下json:

      “发票”:{ “米”:{ “:数字”:{ "S":"XPN1052" }“:日期”:{ “S”:“2022 年 2 月 17 日” } } }

      您可以使用以下代码插入发票记录:

       ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
                          {":invoice", new AttributeValue { M = new Dictionary<string, AttributeValue>{
                              {":date", new AttributeValue { S =  invoice.TxnDate.ToString("MM-dd-yyyy") }},
                              {":number", new AttributeValue{ S = invoice.DocNumber } } }
                          } }},
                      UpdateExpression = "SET invoice = :invoice",
      

      【讨论】:

        【解决方案5】:

        为了根据给定字典使用各种键(最终是 Dynamodb 中的列)动态插入/更新 Dynamodb 项目,我们可以构造查询字符串,如下所示:

        # given dictionary with needs to be dumped into dynamodb
        dict_to_insert = {'column1':'value1', 
                          'column2.subdocument1':{'subkey1':'subvalue1',
                                                  'subkey2':'subvalue2'}...}...
        
        # placeholder variables
        # Using upsert for insert/update mllog records on dynamodb
        query = "SET"
        values_dict = {}
        names_dict = {}
        i = 0
        
        # iterating over given dictionary and construct the query
        for key, value in dict_to_insert.items():
        
                # if item key column provide in the given dictionary
                # then it should be skipped
                if key == 'ITEM_KEY_NAME':
                    i += 1
                    continue
        
                # None values causing error on update_item 
                # So, better to ignore them as well
                if value is not None:
        
                    # if_not_exists method prevents overwriting existing 
                    # values on columns
                    query += " " + "#k_" + str(i) + " = if_not_exists(#k_" + str(i) + \
                             ", :v_" + str(i)+")"
                    if key != list(dict_to_insert.keys())[-1]:  # if not the last attribute add ,
                        query += ","
        
                    # Defining dynamodb columns and their corresponding values
                    values_dict["#k_" + str(i)] = key
                    names_dict[":v_" + str(i)] = value
                i += 1
        

        一旦我们构造了如上所示的查询字符串,我们就可以放心地在 Dynamodb 上运行我们的 update_item 方法:

        # table obj here is boto3 dynamodb resource instance
        table.update_item(
            TableName='DYNAMODB_TABLENAME',
            Key={'ITEM_KEY_NAME': 'ANY_VALUE_AS_KEY'},
            UpdateExpression=query.strip(),
            ExpressionAttributeNames=names_dict,
            ExpressionAttributeValues=values_dict)
        

        【讨论】:

          猜你喜欢
          • 2022-11-02
          • 1970-01-01
          • 2016-12-07
          • 1970-01-01
          • 2011-08-04
          • 1970-01-01
          • 1970-01-01
          • 2019-11-06
          • 1970-01-01
          相关资源
          最近更新 更多