在一个解析器V.S.中解析所有字段每个解析器中的resolve字段

时间:2018-09-11 09:22:12

标签: graphql graphql-js

这是我的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内,它解析独立解析器中Book的每个字段。

我发现resovlers1resolvers2都可以正常工作。我可以得到如下正确的响应:

{
  "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 个答案:

答案 0 :(得分:1)

resolver2更好,因为如果您的请求中不包含author,它不会对数据库进行无用的调用。

答案 1 :(得分:1)

resolver1是性能复杂度的折衷。解析器一的主要论据是数据库通常具有resolver2无法使用的联接。例如,书籍+作者查询可以用单个SQL语句表示。即使使用Dataloader,与版本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查询直接转换为数据库查询。