简体   繁体   English

如何创建可以“完成”类型的 GraphQL 解析器

[英]How to create a GraphQL resolver that can ‘complete’ a type

Let's say we have a mutation that returns an array of objects with only the property id .假设我们有一个突变,它返回一个只有属性id的对象数组。 To “complete” this type we have to create a resolver for every single property of this object.为了“完成”这个类型,我们必须为这个对象的每个属性创建一个解析器。

Instead I'd like to be able to create a resolver that can complete an object.相反,我希望能够创建一个可以完成对象的解析器。

Below an example of a query that sends a list of heroes and a mutation to favorite one.下面是一个查询示例,该查询发送英雄列表和最喜欢的英雄的突变。 The resolver of the mutation setFavorite(id) returns only a list of IDs . mutation setFavorite(id)的解析器仅返回IDs列表。

type Query {
  heroes(first: Int = 10) [Hero]
}

type Hero {
  id: ID!
  title: String!
}

type Mutation {
  setFavorite(id: ID!): [Hero]
}
const resolvers = {
  Query: {
    heroes(_, {first}, {heroes}) {
      return heroes.get({first});
    }
  },
  Mutation: {
    setFavorite(_, {id}, {favorites}) {
      await favorites.setFavorite(id);
      return favorites.getAll(); // <<<< these are only IDs
    }
  }
}

Is it possible to create a resolver, that "completes" a type?是否可以创建一个“完成”类型的解析器?

const resolvers = {
  Hero: {
//  vvvvvv something like this
    __type(parent, _, {heroes}) {
      if (parent.id) {
        return heroes.getOne({id: parent.id});
      }
    }
  }
}

Only fields are resolved , so you can only write resolvers for fields, not types.只有字段被解析,所以你只能为字段编写解析器,而不是类型。 Your options are:您的选择是:

  • Change methods like getAll to actually return instances of the models in question instead of just returning the IDs.更改getAll方法以实际返回相关模型的实例,而不仅仅是返回 ID。

  • Map the returned IDs to model instances inside each resolver.将返回的 ID 映射到每个解析器内的模型实例。

  • Write a resolver for each child field:为每个子字段编写一个解析器:

const resolvers = {
  Hero: {
    title: (id, args, ctx) => {
      const hero = await ctx.dataloaders.hero.findById(id)
      return hero.title
    },
    someOtherField: (id, args, ctx) => {
      const hero = await ctx.dataloaders.hero.findById(id)
      return hero.someOtherField
    },
  },
}

Notice that we use dataloader in this example.请注意,我们在此示例中使用了dataloader This lets us batch the calls to findById and avoids calling the method twice for the same id.这让我们可以批量调用findById并避免为相同的 id 调用该方法两次。 You shouldn't use this pattern without DataLoader;你不应该在没有 DataLoader 的情况下使用这种模式; otherwise you'll end up with unnecessary additional calls to your database.否则,您最终会对数据库进行不必要的额外调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM