AWS appsync query resolver

2019-08-22 02:46发布

问题:

Currently I have my resolver as a lambda function :

import boto3
from boto3.dynamodb.conditions import Key

def lambda_handler(event, context):

  list = []
  for device in event['source']['devices'] :
      dynamodb = boto3.resource('dynamodb')
      readings  = dynamodb.Table('readings')
      response = readings.query(
          KeyConditionExpression=Key('device').eq(device['device'])
      )
      items = response['Items']
      list.extend(items)
  return list

I would like to be able to have this as a VTL resolver on the dynamodb. My problem is that my table has a sort key

This means I can't use a batch resolver to query on a bunch of id's because I would also need to provide the sort key, and I just want all the results by primary partition key.

How do you query with a bunch of ids using VTL, basically replicating my lambda function in VTL. Is this even possible ?

Schema added, please excuse the mess it is a work in progress and am attempting many things. Still very new to graphQL

type Device {
    id: String
    device: String!
}

input DeviceInput {
    id: String
   device: String!
}

type DeviceReadings {
   devices: [Device]
}

type Mutation {
    createDevice(input: DeviceInput): Device
}

type PaginatedDevices {
   devices: [Device]
   readings: [Reading]
   cows: [cow]
   nextToken: String
}

type Query {
    getAllUserDevices(nextToken: String, count: Int): PaginatedDevices
    getAllDeviceReadings: DeviceReadings
    getAllUserReadings: DeviceReadings
    getAllReadings(deviceId: String!): Readings  
    getCowReadings(cowId: String!): UserCowReadings
}

type Reading {
   device: String
   time: Int
   cow: Int
   battery: String
}

type Readings {
    items: [Reading]
}

type UserCowReadings {
    devices: [Device]
    readings: [Reading]
}

type cow {
    id: Int
    device: String
    nait: String
}  

schema {
    query: Query
    mutation: Mutation
}

回答1:

Yes you can do this but you will need to tweak your schema a bit. In that lambda you are essentially saying "for each device do a DynamoDB query to get the most recent readings for that device". Conceptually I would say that devices have many readings. With this in mind, lets make a schema:

type Device {
  id: ID!
  name: String
  # Get the most recent readings for this device.
  # Do a Query where "device = $ctx.source.id"
  readings(limit: Int, nextToken: String): ReadingConnection 
}

type Reading {
  # Use the source's device id in the table to fetch the real device
  # GetItem where device = $ctx.source.device (and any sort key condition)
  device: Device 
  time: Int
  cow: Int
  battery: String
}

type ReadingConnection {
  items: [Reading]
  nextToken: String
}

type DeviceConnection {
  items: [Device]
  nextToken: String
}

type Query {
  getAllDevices(limit: Int, nextToken: String): DeviceConnection
}

You may then paginate through your devices and paginate through each devices readings separately:

query GetAllDevicesAndReadings {
  getAllDevices(first: 10) {
    items {
      id
      name
      readings(limit: 10) {
        time
        cow
        battery
      }
    }
  }
}

I recommend using the drop down in the AppSync console's resolver page to get more ideas for what you can do with the resolver VTL to implement these GetItems and Queries. This is a good starting point. Let me know if you have trouble implementing the VTL.