简体   繁体   English

在 DynamoDB python boto3 中执行 update_item 时出错

[英]Error doing update_item in DynamoDB python boto3

I have a table in DynamoDB that holds a bunch of documents for me.我在 DynamoDB 中有一个表,它为我保存了一堆文档。 The documents have the following fields: computedID (Primary partition key), publication_timestamp, displayTitle, displayText, displayUrl, producer and tags.这些文档具有以下字段:computedID(主分区键)、publication_timestamp、displayTitle、displayText、displayUrl、producer 和 tags。

I'd like to do update_item on the table, so that a record gets updated only if any of the fields publication_timestamp, displayTitle, displayText, displayUrl, producer and tags has changed.我想在表上执行 update_item,以便仅当任何字段publication_timestamp、displayTitle、displayText、displayUrl、producer 和tags 发生更改时才会更新记录。 If the record is totally new it will be simply inserted in the table.如果记录是全新的,它将被简单地插入到表中。

The problem is that not all the existing documents in the table or the incoming documents have displayTitle, displayText, displayUrl and tags.问题在于,并非表中的所有现有文档或传入的文档都具有 displayTitle、displayText、displayUrl 和标签。 They may miss any number of these fields.他们可能会遗漏任意数量的这些字段。

I have tried the following:我尝试了以下方法:

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('project_Incoming_Data')
print("Sending documents to DynamoDB...")

for item in Docs:
    try:
        response=table.update_item(
            Key={"computedID":item["computedID"]},
            UpdateExpression="SET publication_timestamp = :time, displayTitle= :title, displayText= :text, producer = :p, tags= :tags, displayUrl= :url, time_to_live= :ttl",
            ConditionExpression= "publication_timestamp <> :time OR (attribute_exists(displayTitle) AND displayTitle <> :title) OR (attribute_exists(displayText) AND displayText <> :text) OR producer <> :p OR (attribute_exists(tags) AND tags <> :tags) OR (attribute_exists(displayUrl) AND displayUrl <> :url)",
            ExpressionAttributeValues={
                    ":time":item["publication_timestamp"],
                    ":ttl":item["time_to_live"],
                    ":title":item["displayTitle"],
                    ":text":item["displayText"],
                    ":p":item["producer"],
                    ":tags":item["tags"],
                    ":url":item["displayUrl"]
            },
            ReturnValues="UPDATED_NEW"
            )
        print("response is: "+str(response))
    except Exception as e:
        print (e)
print("Done with sending documents to DynamoDB")

I still am unable to get some of my documents into DynamoDB.我仍然无法将我的一些文档放入 DynamoDB。 The error I get is 'displayText'!我得到的错误是“displayText”! I am guessing that the mechanism I have in place for making sure that the field exists on the record doesn't work for documents that don't have that field.我猜测我为确保该字段存在于记录中而采用的机制不适用于没有该字段的文档。

Any idea how to fix this?知道如何解决这个问题吗?

I found the solution!我找到了解决方案! The problem was that even though a document could miss any of the displayText, displayTitle, tags or displayUrl fields, still all three of UpdateExpression, ConditionExpression and ExpressionAttributeValues were considering those fields for the document.问题在于,即使文档可能会遗漏任何 displayText、displayTitle、tags 或 displayUrl 字段,但 UpdateExpression、ConditionExpression 和 ExpressionAttributeValues 中的所有三个字段仍在考虑文档的这些字段。 The solution is to construct them for each document separately based on the fields present in the document.解决方案是根据文档中存在的字段分别为每个文档构建它们。

def send_docs_to_DynamoDB(Docs):
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('Compete_Dental_Incoming_Data')
    print("Sending documents to DynamoDB...")

    for item in Docs:
            expression_attribute_values={
                    ":time":item["publication_timestamp"],
                    ":ttl":item["time_to_live"],
                    ":p":item["producer"]
            }
            update_expression="SET publication_timestamp = :time, producer = :p, time_to_live= if_not_exists(time_to_live, :ttl)"
            condition_expression= "publication_timestamp <> :time OR producer <> :p"
            try:
                    if 'displayTitle' in item.keys():
                            update_expression+=", displayTitle= :title"
                            expression_attribute_values[":title"]=item["displayTitle"]
                            condition_expression+=" OR displayTitle <> :title"
                    if 'displayText' in item.keys():
                            update_expression+=", displayText= :text"
                            expression_attribute_values[":text"]=item["displayText"]
                            condition_expression+=" OR displayText <> :text"
                    if 'displayUrl' in item.keys():
                            update_expression+=", displayUrl= :url"
                            expression_attribute_values[":url"]=item["displayUrl"]
                            condition_expression+=" OR displayUrl <> :url"
                    if 'tags' in item.keys():
                            update_expression+=", tags= :tags"
                            expression_attribute_values[":tags"]=item["tags"]
                            condition_expression+=" OR tags <> :tags"

                    response=table.update_item(
                            Key={"computedID":item["computedID"]},
                            UpdateExpression=update_expression,
                            ConditionExpression= condition_expression,
                            ExpressionAttributeValues=expression_attribute_values,
                            ReturnValues="UPDATED_NEW"
                            )
                    print("response is: "+str(response))
            except Exception as e:
                    print (e)
    print("Done with sending documents to DynamoDB")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM