【问题标题】:How to create a nested resolver in apollo graphql server如何在 apollo graphql 服务器中创建嵌套解析器
【发布时间】:2017-04-15 13:43:37
【问题描述】:

给定以下 apollo 服务器 graphql 架构 我想将它们分解为单独的模块,因此我不希望在根查询模式下进行作者查询..并希望将其分开。所以我在将其添加到根查询之前添加了另一个名为 authorQueries 的层

type Author {
    id: Int,
    firstName: String,
    lastName: String
}  
type authorQueries {
    author(firstName: String, lastName: String): Author
}

type Query {
    authorQueries: authorQueries
}

schema {
    query: Query
}

我尝试了以下..您可以看到在指定作者函数之前添加了 authorQueries 作为另一层。

Query: {
    authorQueries :{
        author (root, args) {
            return {}
       }
    }
}

在 Graphiql 中查询时,我还添加了那个额外的层..

{
    authorQueries {
        author(firstName: "Stephen") {
            id
        }
    }
}

我收到以下错误。

"message": "Resolve function for \"Query.authorQueries\" returned undefined",

【问题讨论】:

标签: graphql apollostack apollo-server


【解决方案1】:

Apollo Official 相关文档(Great 内有示例):

解析器链

https://www.apollographql.com/docs/apollo-server/data/resolvers/#resolver-chains

/* code from:
https://www.apollographql.com/docs/apollo-server/data/resolvers/#resolver-chains
*/

const { ApolloServer, gql } = require('apollo-server');

const libraries = [
  {
    branch: 'downtown'
  },
  {
    branch: 'riverside'
  },
];

// The branch field of a book indicates which library has it in stock
const books = [
  {
    title: 'The Awakening',
    author: 'Kate Chopin',
    branch: 'riverside'
  },
  {
    title: 'City of Glass',
    author: 'Paul Auster',
    branch: 'downtown'
  },
];

// Schema definition
const typeDefs = gql`

# A library has a branch and books
  type Library {
    branch: String!
    books: [Book!]
  }

  # A book has a title and author
  type Book {
    title: String!
    author: Author!
  }

  # An author has a name
  type Author {
    name: String!
  }

  # Queries can fetch a list of libraries
  type Query {
    libraries: [Library]
  }
`;

// Resolver map
const resolvers = {
  Query: {
    libraries() {

      // Return our hardcoded array of libraries
      return libraries;
    }
  },
  Library: {
    books(parent) {

      // Filter the hardcoded array of books to only include
      // books that are located at the correct branch
      return books.filter(book => book.branch === parent.branch);
    }
  },
  Book: {

    // The parent resolver (Library.books) returns an object with the
    // author's name in the "author" field. Return a JSON object containing
    // the name, because this field expects an object.
    author(parent) {
      return {
        name: parent.author
      };
    }
  }

  // Because Book.author returns an object with a "name" field,
  // Apollo Server's default resolver for Author.name will work.
  // We don't need to define one.
};

// Pass schema definition and resolvers to the
// ApolloServer constructor
const server = new ApolloServer({ typeDefs, resolvers });

// Launch the server
server.listen().then(({ url }) => {
  console.log(`?  Server ready at ${url}`);
});

【讨论】:

    【解决方案2】:

    我发现在父字段返回类型上返回函数会导致 this arg 被绑定,并破坏解析器接口 b/c 嵌套解析器不会将父级作为第一个参数。

    对于内联类型定义

    import {
      graphql,
    } from 'graphql';
    
    import {
      makeExecutableSchema, IResolverObject
    } from 'graphql-tools';
    
    const types = `
    type Query {
      person: User
    }
    
    type User {
      id: ID
      name: String,
      dog(showCollar: Boolean): Dog
    }
    
    type Dog {
      name: String
    }
    `;
    
    const User: IResolverObject = {
      dog(obj, args, ctx) {
        console.log('Dog Arg 1', obj);
        return {
          name: 'doggy'
        };
      }
    };
    
    const resolvers = {
      User,
      Query: {
        person(obj) {
          console.log('Person Arg 1', obj);
          return {
            id: 'foo',
            name: 'bar',
          };
        }
      }
    };
    
    const schema = makeExecutableSchema({
      typeDefs: [types],
      resolvers
    });
    
    const query = `{ 
      person {
        name,
        dog(showCollar: true) {
          name
        }
      }
     }`;
    
    
    graphql(schema, query).then(result => {
      console.log(JSON.stringify(result, null, 2));
    });
    
    // Person Arg 1 undefined
    // Dog Arg 1 { id: 'foo', name: 'bar' }
    // {
    //   "data": {
    //     "person": {
    //       "name": "bar",
    //       "dog": {
    //         "name": "doggy"
    //       }
    //     }
    //   }
    // }
    

    您也可以使用addResolveFunctionsToSchema,如下所示。

    https://gist.github.com/blugavere/4060f4bf2f3d5b741c639977821a254f

    【讨论】:

      【解决方案3】:

      要创建“嵌套”解析器,只需在父字段的返回类型上定义解析器。在这种情况下,您的 authorQueries 字段返回类型 authorQueries,因此您可以将解析器放在那里:

      {
        Query: { authorQueries: () => ({}) },
        authorQueries: {
          author(root, args) {
            return "Hello, world!";
          }
        }
      }
      

      因此,从技术意义上讲,不存在嵌套解析器之类的东西 - 每个对象类型都有一个平面的字段列表,并且这些字段具有返回类型。 GraphQL 查询的嵌套是结果嵌套的原因。

      【讨论】:

      • 有没有更好的方法,比如为作者类型定义一个解析器,它使用一些过度给定的根参数的值?当我这样做时,我会为每次使用其他类型的作者制作解析器
      • 是的,您需要为每个返回作者的字段定义一个解析器,至少在当前的 GraphQL 实现中是这样。未来可能会更好。
      • 我喜欢你关于 GraphQL 没有“嵌套”解析器的观点。在我意识到这一点之前,我一直在努力阅读大量文档......
      • 这不适用于深度 > 1。解析器只能为查询返回的类型的属性定义,不能为这些属性的属性定义。除非我遗漏了什么,否则这是一个主要的性能问题,因为您最终会执行并非每个请求都需要的计算。
      猜你喜欢
      • 2019-07-15
      • 2018-08-27
      • 2021-08-22
      • 2018-08-25
      • 2016-09-17
      • 1970-01-01
      • 2021-06-04
      • 2019-11-06
      • 2018-01-05
      相关资源
      最近更新 更多