流星Apollo GraphQL接口:返回对象数组并在另一个解析器中调用解析器

时间:2018-11-10 23:33:59

标签: meteor graphql apollo apollo-client apollo-server

我在GraphQl interfaces上遇到了一些问题。让我们以文档中的示例为例:

interface Vehicle {
  maxSpeed: Int
}

type Airplane implements Vehicle {
  maxSpeed: Int
  wingspan: Int
}

type Car implements Vehicle {
  maxSpeed: Int
  licensePlate: String
}

type Query {
  vehicle: Vehicle
}

const resolvers = {
  Vehicle: {
    __resolveType(obj, context, info){
      if(obj.wingspan){
        return 'Airplane';
      }

      if(obj.licensePlate){
        return 'Car';
      }

      return null;
    },
  },
  Query: {
    vehicle: () => { 
       // Query Airplane and Car an merge in one single array.
    }
  },
};

背景:我为每种接口实现创建2个不同的DBs:一个用于Car,一个用于Airplane。但是我没有为DB创建Vehicle,因为它只是一个interface本身并不保留数据。 (我希望这很好)

第一个问题是如何访问CarAirplane resolvers以在DBs中查询它们各自的Vehicle resolver?因此,在Query.vehicle()中,我只想调用为获取所有汽车而定义的解析器以获取所有汽车,并调用为获取飞机而将其获取以获取DB中的所有飞机的解析器。 (请注意,使用Car.find().fetch()并不总是有效的,因为在执行查询之前,还需要执行许多其他查询,还可以避免代码重复)。

第二个问题是在示例中,obj.wingspan假定obj应该是一个对象。因此,从Query.vehicle()返回数组将无济于事,因为此查询在Vehicle.__resolveType中使用。因此,根据我对GraphQl接口的经验,它仅返回查询中的单个对象。 我的目标是通过以下查询获得:

{
  vehicle {
    maxSpeed

    ... on Car {
            licensePlate
    }
    ... on Airplane {
      wingspan
    }
  }
}

以下结果:

{
  "data": {
    "car": [
      {
        "maxSpeed": 200,
        "licensePlate": 1.8
      },
      {
        "maxSpeed": 120,
        "licensePlate": "String"
      },
      ...
    ],
    "Airplane": [
      {
        "maxSpeed": 500,
        "wingspan": "String"
      },
      {
        "maxSpeed": 700,
        "wingspan": 1.5
      },
      ...
    ]
  }
}

1 个答案:

答案 0 :(得分:0)

听起来您可能正在尝试返回多个对象。如果是这样,则需要返回一个对象数组:

type Query {
  vehicles: [ Vehicle ]
}

如果您只是想通过ID返回单个对象,则在车辆解析器中,只需尝试两个数据库并返回结果为一个数据库即可:

const resolvers = {
  Query: {
    vehicle: (parent, args) => {
      const { id } = args;

      const [ car, plane ] = await Promise.all(
        await carDB.get(id),
        await planeDB.get(id)
      )

      return car || plane
    }
  }
}

修改

以防您尚未了解此信息:

要获得您所描述的内容,您还需要其他内容:

类型定义

interface Vehicle {
  maxSpeed: Int
}

type Airplane implements Vehicle {
  maxSpeed: Int
  wingspan: Int
}

type Car implements Vehicle {
  maxSpeed: Int
  licensePlate: String
}

type Query {
  vehicles: VehiclesConnection
}

type VehiclesConnection {
  car: [ Car ]
  airplane: [ Airplane ]
}

解析器

const resolvers = {
  Query: {
    vehicle: () => {
      const [ cars, planes ] = await Promise.all(
        await carDB.findAll(),
        await planeDB.findAll()
      )

      return { cars, planes }
    }
  }
}

查询

{
  vehicle {
    car {
      maxSpeed
      licensePlate
    }
    airplane {
      maxSpeed
      wingspan
    }
  }
}

替代查询

{
  vehicle {
    car {
      ...VehicleFragment
    }
    airplane {
      ...VehicleFragment
    }
  }
}

fragment VehicleFragment on Vehicle {
  maxSpeed

  ... on Car {
    licensePlate
  }
  ... on Airplane {
    wingspan
  }
}

结果

{
  "data": {
    "car": [
      {
        "maxSpeed": 200,
        "licensePlate": 1.8
      },
      {
        "maxSpeed": 120,
        "licensePlate": "String"
      },
      ...
    ],
    "Airplane": [
      {
        "maxSpeed": 500,
        "wingspan": "String"
      },
      {
        "maxSpeed": 700,
        "wingspan": 1.5
      },
      ...
    ]
  }
}