GraphQL, как заставить распознаватель извлекать данные только при необходимости? - PullRequest
0 голосов
/ 27 мая 2018

У меня есть два типа GraphQL:

type Author {
  id: String!
  name: String!
}

type Book {
  id: String!
  author: Author!
  name: String!
}

В моей базе данных это реализовано с помощью внешнего ключа в таблице books:

таблица authors (псевдокод)

`id` INTEGER UNSIGNED
`name` STRING

таблица books (псевдокод)

`id` INTEGER UNSIGNED
`author_id` INTEGER UNSIGNED REFERENCE `authors.id`
`name` STRING

Поэтому, когда я разрешаю запрос GraphQL, например:

query allTheBooks {
  id
  name
  author {
    id
  }
}

Я не хочу делать другой запрос SQL, кроме того, который получит список книг, поскольку у меня уже есть данные в поле books.author_id.

Поэтому я заменяю следующий код(js):

Book: {
  async author(book, args, context, info) {
    // this code trigger a database SELECT query that fetch all the fields of the author row associated with the book
    return book.author().get();
  }
}

by:

Book: {
  async author(book, args, context, info) {
    return {
      id: book.author_id,
    }
  }
}

И это хорошо работает!

У меня есть только 1 SQL-запрос, где у меня было 1 + N (N равноколичество строк, возвращаемых первым запросом).

Но как я могу вернуть другие поля, не отправляя запрос по полю?

Я полагаю, что это возможно, возвращая уникальное обещание для всехполя, которые будут обрабатываться со всем содержимым строки author, но мне интересно, есть ли более чистый способ ...

Заранее спасибо за ваш ответ!

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Вам не нужно делать 1 + N запрос.Вы можете пакетировать N запросов в 1. Просто проверьте https://github.com/facebook/dataloader.

0 голосов
/ 27 мая 2018

На данный момент я нахожу более или менее чистый способ сделать это:

Book: {
  async author(book, args, context, info) {
    let authorPromise = null;

    async function getAuthor() {
      if (authorPromise === null) {
        authorPromise = book.author().get();
      }

      return authorPromise;
    }

    return new Proxy({}, {
      async get({}, name) {
        if (name === "id") {
          return book.author_id;
        }

        if (name in authorFields) {
          const author = await getFile();
          return author[name];
        }
      },
    });
  }
}

Это гарантирует, что я могу сделать только один запрос на строку, но оставлю мне другой вопрос о соединении таблиц, но я выложу здесь : -)

...