在 Python Graphene 中执行嵌套查询,在模式中具有不同类型

perform nested query in Python Graphene with distinct types in schema

我有以下来自数据库的数据结构:

[
   {
    'time': '2019-07-19T12:57:17Z', 
    'bizLocation': 'urn:epc:id:sgln:bizLocation.Company.3',
    'city': 'dallas',
    'countryCode': 'US',
    'humid': 49, 
    'sID': '40:61:32:22:11:00',
    'site': 'factory',
    'stype': 'BME280',
    'temp': 22.941
   }
]

我希望创建一个 GraphQL API 来查询数据库并在以下输出中提供查询:

[
{
   sID: String (same as sID),
   sType: String (same as sType),
   bizLocation: String (same as bizLocation),
   values: [
       {
         timestamp: Datetime (same as time),
         value: Float (value of 'temp')
         mType: 'temp'
       },
       {
         timestamp: Datetime (same as time),
         value: Float (value of 'humid'),
         mType: 'humid'
       }
   ]
}
]

我正在使用 Graphene 来测试它是否可行。目前我只是在玩弄这个想法并尝试制作以下 GraphQL 模式:

type SensorDoc {
   sID: String
   sType: String
   bizLocation: String
   values: [SensorData]
}

type SensorData {
   timestamp: String
   value: Float
   mType: String
}

翻译成石墨烯如下:

import graphene

class SensorData(graphene.ObjectType):
    timestamp = graphene.DateTime()
    value = graphene.Float()
    mType = graphene.String()

class SensorDoc(graphene.ObjectType):
    sId = graphene.String()
    sType = graphene.String()
    bizLocation = graphene.String()
    values = graphene.List(SensorData)

class Query(graphene.ObjectType):

    sensor_data = graphene.List(SensorDoc)
    def resolve_sensor_data(self, info):
        # DB Query Logic Here!!

        output = [] # output to return

        for each_point in list_result:
            SensorDoc(sId=each_point['sID'], sType=each_point['stype'], 
                bizLocation=each_point['bizLocation'],
                SensorData(timestamp=each_point['time'], 
    value=each_point['humid'], mType='humid') # <---- This is a SyntaxError
            )

            output.append(SensorDoc)
        return output

这行不通,因为 SensorData 不会作为关键字参数传递。

我对尝试石墨烯完全陌生,想知道当查询应如下所示时如何实现:

query{
   sensorData {
       sID
       sType
       bizLocation
       values {
          timestamp
          value
       }
   }
}

我能够通过解决 SensorDoc class 中的 values 来解决这个问题,如下所示:

class SensorData(graphene.ObjectType):
    timestamp = graphene.String()
    temp = graphene.Float()
    humid = graphene.Float()


class SensorDoc(graphene.ObjectType):
    sId = graphene.String()
    sType = graphene.String()
    bizLocation = graphene.String()
    values = graphene.List(SensorData)

    def resolve_values(parent, info):
        # DB Query Logic
        output = [] # output to return

        for each_point in list_result:
            output.append(
               SensorData(timestamp=each_point['time'], temp=each_point['temp'], humid=each_point['humid'])
            )
        return output

并且在主要 Query Class 中,保留了 resolve_sensor_doc 解析器:

class Query(graphene.ObjectType):
    sensor_doc = graphene.List(SensorDoc)

    def resolve_sensor_doc(self, info):
        # DB Query Logic

        output = []
        for each_point in list_result:
            output.append(
                SensorDoc(
                    sId=each_point['sID'], 
                    sType=each_point['stype'], 
                    bizLocation=each_point['bizLocation']
                )
            )
        return output

终于执行了:

schema = graphene.Schema(query=Query)

result = schema.execute(
    '''
    query {
        sensorDoc{
            sId
            sType
            bizLocation
            values {
                timestamp
                temp
                humid
            }
        }
    }
    '''
)

items = dict(result.data.items())
print(json.dumps(items, indent=4))

给我提供如下输出:

{
    "sensorDoc": [
        {
            "sId": "60:64:05:9C:DF:F2",
            "sType": "BME280",
            "bizLocation": "urn:epc:id:sgln:bizLocation.3",
            "values": [
                {
                    "timestamp": "2019-07-19T12:57:17Z",
                    "temp": 22.941,
                    "humid": 49.0
                },
                {
                    "timestamp": "2019-07-19T12:57:19Z",
                    "temp": 22.981,
                    "humid": 47.0
                },
                {
                    "timestamp": "2019-07-19T12:57:21Z",
                    "temp": 23.001,
                    "humid": 47.0
                }
            ]
        },
        {
            "sId": "60:64:05:9C:DF:F2",
            "sType": "BME280",
            "bizLocation": "urn:epc:id:sgln:bizLocation.3",
            "values": [
                {
                    "timestamp": "2019-07-19T12:57:17Z",
                    "temp": 22.941,
                    "humid": 49.0
                },
                {
                    "timestamp": "2019-07-19T12:57:19Z",
                    "temp": 22.981,
                    "humid": 47.0
                },
                {
                    "timestamp": "2019-07-19T12:57:21Z",
                    "temp": 23.001,
                    "humid": 47.0
                }
            ]
        },
        {
            "sId": "60:64:05:9C:DF:F2",
            "sType": "BME280",
            "bizLocation": "urn:epc:id:sgln:bizLocation.3",
            "values": [
                {
                    "timestamp": "2019-07-19T12:57:17Z",
                    "temp": 22.941,
                    "humid": 49.0
                },
                {
                    "timestamp": "2019-07-19T12:57:19Z",
                    "temp": 22.981,
                    "humid": 47.0
                },
                {
                    "timestamp": "2019-07-19T12:57:21Z",
                    "temp": 23.001,
                    "humid": 47.0
                }
            ]
        }
    ]
}