首页 > 解决方案 > 如何使用来自 Pandas DataFrame 的值更新 DynamoDB 列,使用 ID 作为公共值

问题描述

我在 dynamoDB 中有一个名为返回门户的表,我还有一个包含两列 order_name 和 return_status 的 DataFrame。

我需要使用我的 DF (df2) 中的值更新 dynamoDB 表,return_status 列,使用 order_name 作为两个数据集的 ID,并且 order_name 可以在 DynamoDB 表中出现多次,但在 df2 中只能出现一次。我遇到的问题是我真的不明白这怎么可能。我试图自己把一些东西放在一起,但它不起作用,见下面的代码:

import boto3
from boto3.dynamodb.conditions import Key
import json
import pyodbc
import pandas as pd
import numpy as np
import datetime
from func.excelfunction import *
from datetime import datetime as dt
from datetime import timedelta
import requests
import csv
import os
import math
from sql_server.sql_server import *

#Connect to ETL DB

df1 = run_sql_df('SET NOCOUNT ON; select distinct order_number, return_status from etl_db.dbo.shopify_returns_portal')
df1 = df1.astype({"order_number":"str","return_status":"str"})

filename = 'test_file.csv'

df1.to_csv(str(filename),index=False)

df2 = pd.read_csv('test_file.csv')
df2 = df2.astype({"order_number":"str","return_status":"str"})


#create update statement for DynamoDB

def update_status(order_number,return_status, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource("dynamodb",aws_access_key_id ="XXXXXXXXXXXX",aws_secret_access_key = "XXXXXXXXXXXXXXXXXX",region_name = "eu-west-1")

    table = dynamodb.Table('returns-portal')

    response = table.update_item(
        Key={
            'order_number': df2.order_number
        },
        UpdateExpression="set return_status =:r",
        ExpressionAttributeValues={
            ':r': df2.return_status
        },
        ReturnValues="UPDATED_NEW"
    )
    return response


if __name__ == '__main__':

    update_response = update_status(df2.order_number,df2.return_status)
    print("Update movie succeeded:")
    pprint(update_response, sort_dicts=False)

我得到的错误是:

TypeError: Unsupported type "<class 'pandas.core.series.Series'>" for value "0        25061198
1        25061184
2        14441634
3        14441639
4        25061205
5     26054929503
6        25061203
7        25061186
8        14441629
9        25061187
10       25061201
11       25061196
12       14441636
13       25061177
14       25061194
15       14441641
16       25061189
17       25061206
18       25061204
19       14441628
20       25061199
21       25061185
22       14441633
23       25061197
24       25061180
25       14441638
26       25061192
27       25061195
28       14441637
29       25061193
30       25061200
31       14441635
Name: order_number, dtype: object"

我强烈怀疑我做错了,但我在网上找不到任何关于人们使用 dataFrame 更新 DynamoDB 表的信息。看着它,我觉得你可能不得不遍历 dynamoDB 中的行,但我不知道是否是这种情况,或者如何去做。

非常感谢所有帮助。

标签: pythonpandasamazon-dynamodbboto3

解决方案


您不是在遍历 order_number 或 return_status 列表,而是在发送整个列(或系列)。

首先,不知道你为什么要重新读取 csv 到 df2,只使用 df1 - 它是相同的数据......

要获取要迭代的列表,您可以使用 zip 或 to_dict 如前所述。这是一个 zip 示例。它给出了一个元组列表。

onum_status_pair_list = list(zip(df1['order_number'], df1['return_status']))

然后你想迭代这个。更新您的代码:

def update_status(order_number,return_status, dynamodb=None):
    if not dynamodb:
        dynamodb = boto3.resource("dynamodb",aws_access_key_id ="XXXXXXXXXXXX",aws_secret_access_key = "XXXXXXXXXXXXXXXXXX",region_name = "eu-west-1")

    table = dynamodb.Table('returns-portal')

    response = table.update_item(
        Key={
            'order_number': order_number
        },
        UpdateExpression="set return_status =:r",
        ExpressionAttributeValues={
            ':r': return_status
        },
        ReturnValues="UPDATED_NEW"
    )
    return response


if __name__ == '__main__':
    # note use of parenthesis to iterate list of tuples
    for (onum, stat) in onum_status_pair_list:
        update_response = update_status(onum,stat)
        print("Update movie succeeded:")
        pprint(update_response, sort_dicts=False)

如果您遇到问题,请给我留言。没有办法测试这个...


推荐阅读