将 Pandas 中的 VARIANT 类型插入到 Snowflake 中

tan*_*nia 7 python pandas snowflake-cloud-data-platform

我正在尝试将 Pandas 数据帧中的数据插入 Snowflake 中的表中,但我无法弄清楚如何正确执行此操作。首先,我在 Snowflake 中创建了一个表,其中包含一些类型为 的列VARIANT。例如:

CREATE OR REPLACE TABLE
    mydatabase.myschema.results(
        DATE date, 
        PRODUCT string, 
        PRODUCT_DETAILS variant, 
        ANALYSIS_META variant,
        PRICE float
)
Run Code Online (Sandbox Code Playgroud)

然后在 Pandas 中,我有一个像这样的数据框:

import pandas as pd
record = {'DATE': '2020-11-05',
 'PRODUCT': 'blue_banana',
 'PRODUCT_DETAILS': "{'is_blue': True, 'is_kiwi': nan}",
 'ANALYSIS_META': "None",
 'PRICE': 13.02}
df = pd.DataFrame(record, index=[0])
Run Code Online (Sandbox Code Playgroud)

如您所见,我已将列编码VARIANT为字符串,正如我从snowflake-connector文档中了解到的那样,SnowflakeVARIANT类型映射到strPandas 中的 dtype,反之亦然。

所以,到目前为止我所做的尝试如下:

from snowflake.connector import pandas_tools

pandas_tools.write_pandas(
                conn=conn,
                df=df,
                table_name="results",
                schema="myschema",
                database="mydatabase")
Run Code Online (Sandbox Code Playgroud)

这确实有效,返回

(True,
 1,
 1,
 [('czeau/file0.txt', 'LOADED', 1, 1, 1, 0, None, None, None, None)])
Run Code Online (Sandbox Code Playgroud)

然而,我在 Snowflake 中得到的结果不是正确的VARIANT类型。该字段ANALYSIS_META是正确的NULL,但该字段PRODUCT_DETAILS是类型str。看: 在此输入图像描述

(此外,例如此查询会引发错误:

SELECT * FROM
MYDATABASE.MYSCHEMA.RESULTS
WHERE PRODUCT_DETAILS:is_blue -- should work for json/variant fields
Run Code Online (Sandbox Code Playgroud)

因此,我的问题是:我应该如何正确格式化我的 Pandas 数据框,以便将字段VARIANT作为嵌套字段正确插入雪花表中?我认为将字典转换为字符串可以解决问题,但显然它并没有像我预期的那样工作。我在这里缺少什么?

tan*_*nia 2

经过一番调查,我发现以下解决方案可行:

1. 确保列符合 json 标准

这里的关键是json.dumps将您的数据转换为正确的格式(正确的引用、表示null等)。

import pandas as pd
import json
record = {'DATE': '2020-11-05',
 'PRODUCT': 'blue_banana',
 'PRODUCT_DETAILS': json.dumps({'is_blue': True, 'is_kiwi': None}),
 'ANALYSIS_META': json.dumps(None),
 'PRICE': 13.02}
df = pd.DataFrame(record, index=[0])
Run Code Online (Sandbox Code Playgroud)

2. 确保你使用parse_jsonINSERT迭代

write_pandas我们可以逐行INSERT进入表,确保指定parse_json所需VARIANT类型的列,同时还将值编码为字符串(通过'在其周围放置标记),而不是像最初尝试的那样使用。需要注意的是,如果您有大量数据,此解决方案将会非常慢。

sql = """INSERT INTO MYDATABASE.MYSCHEMA.RESULTS
SELECT
 to_date('{DATE}'),
 '{PRODUCT}',
 parse_json('{PRODUCT_DETAILS}'),
 parse_json('{ANALYSIS_META}'),
 {PRICE}
"""
### CREATE A SNOWFLAKE CONN...

for i, r in df.iterrows():
    conn.cursor().execute(sql.format(**dict(r)))
Run Code Online (Sandbox Code Playgroud)