Интерфейсы Meteor Apollo GraphQL: возврат массива объектов и вызов распознавателя в другом распознавателе

У меня возникли проблемы с GraphQl интерфейсы. Возьмем пример в документе:

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, который не хранит данные в себе. (Надеюсь, это нормально)

Первая проблема заключается в том, как получить доступ к Car и Airplane resolvers, чтобы запросить их соответствующие DBs в Vehicle resolver? Итак, в Query.vehicle() я хотел бы просто вызвать распознаватель, определенный для получения всех автомобилей, чтобы получить все автомобили, и вызвать распознаватель для получения самолетов, чтобы получить все самолеты в БД. (обратите внимание, что использование 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
      },
      ...
    ]
  }
}

person danyhiol    schedule 10.11.2018    source источник


Ответы (1)


Похоже, вы пытаетесь вернуть несколько объектов. Если это так, вам нужно будет вернуть массив объектов:

type Query {
  vehicles: [ Vehicle ]
}

Если вы просто пытаетесь вернуть один объект по идентификатору, в распознавателе вашего автомобиля просто попробуйте обе базы данных и верните одну с результатом:

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
      },
      ...
    ]
  }
}
person Dan Crews    schedule 19.11.2018
comment
Спасибо за Ваш ответ. Я уже понял это. Чего я пытаюсь добиться, так это показанного выше результата с каждой группой БД (Автомобиль, Самолет,...). - person danyhiol; 25.11.2018