代码之家  ›  专栏  ›  技术社区  ›  Lin Du Correcter

解析一个冲突解决程序中的所有字段v.s.解析每个冲突解决程序中的字段

  •  1
  • Lin Du Correcter  · 技术社区  · 6 年前

    这是我的 typeDefs :

    const typeDefs: string = `
      type Book {
        id: ID!
        title: String
        authorId: ID!
        author: User
      }
    
      type User {
        id: ID!
        name: String
      }
    
      type Query {
        books: [Book]!
      }
    `;
    
    export { typeDefs };
    

    resolvers :

    import { IResolvers } from 'graphql-tools';
    import { IBook } from './db';
    
    const resolvers1: IResolvers = {
      Query: {
        books: (_, args, { db }): Promise<IBook[]> => {
          return db.books.map(book => {
            book.author = db.users.find(user => book.authorId === user.id);
            return book;
          });
        }
      }
    };
    
    const resolvers2: IResolvers = {
      Query: {
        books: (_, args, { db }): Promise<IBook[]> => {
          return db.books;
        }
      },
      Book: {
        author: (book, args, { db }) => {
          return db.users.find(user => book.authorId === user.id);
        }
      }
    };
    
    export { resolvers1, resolvers2 };
    

    resolvers1 ,它解析 Book . (添加) author 字段到 book )

    resolvers2 ,它解析 在独立分解器中。

    我发现两者 resovlers1 解决方案2 工作很好。我可以得到这样的正确回答:

    {
      "data": {
        "books": [
          {
            "id": "02wDZbBuMi",
            "title": "Ea repellendus",
            "authorId": "hhP2TtobM",
            "author": {
              "id": "hhP2TtobM",
              "name": "Mrs. Destiney Kerluke"
            }
          },
          {
            "id": "tC3uPfKfUZ",
            "title": "Consectetur fugit",
            "authorId": "k9IHZAtld8",
            "author": {
              "id": "k9IHZAtld8",
              "name": "Mr. Rene Heidenreich"
            }
          }
        ]
      }
    }
    

    他们之间有什么区别?这两种方法正确吗?如果不是,为什么?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Herku    6 年前

    resolver1 是对复杂性能的权衡。解析器1的主要论点是数据库通常具有 resolver2 无法使用。例如,book+author查询可以用单个SQL语句表示。这是一个 巨大的 性能优于版本2,即使使用了数据加载器。现在有人可能会说,我们甚至不知道是否需要作者领域。但是我们可以通过 resolveInfo 争论。可以编写一个函数来快速检查resolveinfo并告诉我们子选择中是否存在字段:

    hasSelection(fieldName: string, resolveInfo: GraphQLResolveInfo): boolean
    

    然后我们可以使用这个函数来检查是否应该进行连接。

    books: (_, args, { db }, resolveInfo): Promise<IBook[]> => {
      if (hasSelection('author', resolveInfo)) {
        // Just an example, there is some more transformation needed
        return db.query('SELECT ... FROM book JOIN author ON book.authorId = author.id');
      }
      return db.query('SELECT ... FROM book');
    }
    

    这可能会在两个因素的作用下更有效。实际上有很多公司都这样做,因为有时候性能是关键。如果这个例子变得更复杂,那么复杂度会显著上升,如果不首先确定它是一个瓶颈,我就不会做出这样的优化。另一方面,有许多项目在“本机graphql”上工作,这意味着它们将graphql查询直接转换为数据库查询。

        2
  •  1
  •   Gabriel Bleu    6 年前

    resolver2 更好,因为如果不包括 author 在你的请求中。