Python psycopg2/SQLAlchemy:使用自定义类型数组参数执行函数

Python psycopg2/SQLAlchemy:使用自定义类型数组参数执行函数,python,postgresql,sqlalchemy,psycopg2,Python,Postgresql,Sqlalchemy,Psycopg2,我有一个自定义postgres类型,如下所示: CREATE TYPE "Sensor".sensor_telemetry AS ( sensorid character varying(50), measurement character varying(20), val numeric(7,3), ts character varying(20) ); 我正在尝试执行对postgres函数的调用,该函数将这种类型的数组作为参数 我使用SQLAlchemy调用

我有一个自定义postgres类型,如下所示:

CREATE TYPE "Sensor".sensor_telemetry AS
(
    sensorid character varying(50),
    measurement character varying(20),
    val numeric(7,3),
    ts character varying(20)
);
我正在尝试执行对postgres函数的调用,该函数将这种类型的数组作为参数

我使用SQLAlchemy调用此函数,如下所示:

result = db.session.execute("""select "Sensor"."PersistTelemetryBatch"(:batch)""", batch)
其中,批处理看起来像:

{
    "batch" : [
        {
            "sensorID" : "phSensorA.haoshiAnalogPh",
            "measurement" : "ph",
            "value": 8.7,
            "timestamp": "2019-12-06 18:32:36"
        },
        {
            "sensorID" : "phSensorA.haoshiAnalogPh",
            "measurement" : "ph",
            "value": 8.8,
            "timestamp": "2019-12-06 18:39:36"
        }
    ]
}
运行此执行时,我遇到以下错误:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'dict'
我猜psycopg2正在抱怨将自定义类型数组条目作为dict,因为我可以将字典作为参数提供给其他pg函数执行,但这些字典不包含在像这种情况下的数组中。我说的对吗


如何将这些对象的数组正确地传递给我的pg函数?

传递数据的一种简单方法是使用Python,让psycopg2处理这些数据,使其适应合适的SQL结构:

from operator import itemgetter

ig = itemgetter("sensorID", "measurement", "value", "timestamp")
batch = {"batch": list(map(ig, batch["batch"]))}
query = """
        SELECT "Sensor"."PersistTelemetryBatch"(
            CAST(:batch AS "Sensor".sensor_telemetry[]))
        """
result = db.session.execute(query, batch)
当您的数据是dict列表时,另一个有趣的选项是使用json_populate_record或json_populate_recordset,但对于那些您必须修复键以匹配的选项:

import json

batch = [{"sensorid": r["sensorID"], 
          "measurement": r["measurement"],
          "val": r["value"],
          "ts": r["timestamp"]}
         for r in batch["batch"]]
batch = {"batch": json.dumps(batch)}

query = """
        SELECT "Sensor"."PersistTelemetryBatch"(ARRAY(
            SELECT json_populate_recordset(
                       NULL::"Sensor".sensor_telemetry,
                       :batch)))
        """
result = db.session.execute(query, batch)

将dicts转换为元组:使用链接答案psycopg/literal响应中的代码,元组列表看起来像['value'、'measurement'、'timestamp'、'sensorID'、'value'、'measurement'、'timestamp'、'sensorID']。我应该在这里提供这些键的值吗?此外,每个元组中值的顺序是否需要与我创建的pgsql类型相同@元组应该包含值,并且它们应该反映用户定义类型的字段顺序。仔细想想,这可能是Python的operator.itemgetter的一个很好的用例,如果给定多个键,iirc将返回值的元组。