resolver1
- компромисс сложности для производительности.Основной аргумент для resolver one состоит в том, что базы данных обычно имеют объединения, которые resolver2
не может использовать.Запрос book + author может, например, быть выражен одним оператором SQL.Это огромное преимущество в производительности по сравнению с версией 2 даже с Dataloader.Теперь можно утверждать, что мы не знаем, нужно ли вообще поле автора.Но мы можем узнать это, используя аргумент resolveInfo
.Можно написать функцию, которая быстро проверяет resolInfo и сообщает нам, присутствует ли поле в подвыборе:
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 непосредственно в запросы к базе данных.