GraphQL:从父解析器获取数据并避免不必要的数据库调用?

时间:2018-07-29 13:57:24

标签: facebook-graph-api graphql express-graphql

在GraphQL中,我有两种类型,即Author和Quotes,如下所示:

  type Author {
    id: Int!
    name: String!
    last_name: String!
    quotes: [Quote!]!
  }

  type Quote {
    id: Int!
    author: Author! 
    quote: String!
  }

我的解析器功能的一部分如下:

  Author: {
    quotes: ({ id }, args, { models, loaders }, info) => {
      return loaders.quotesByIds.load(id);
    }
  }
  Quote: {
    author: (obj, args, { models, loaders }, info) => {
      let author_id = obj.author_id;
      return models.author.findById(author_id);
      //return loaders.authorsById.load(obj.author_id); //for batching.
    }
  }

我已经将Sequelize用作数据库的ORM,而模型表示用于查询数据库的Sequelize对象。 loaders 对象是用于批量处理和缓存的DataLoader对象。

我已使用以下代码成功批量处理了报价请求:

let quotesByIds = new DataLoader(getQuotesByID);
async function getQuotesByID(authorIds){

    let quotes = await models.quote.findAll({ where: { author_id: authorIds } });
    let data = quotes.map((quote) => quote.get({ plain: true }));
    const groupQuotes = _.groupBy(data, 'author_id');
    return authorIds.map(aId => groupQuotes[aId] || []);
}

然后,我每次使用loaders.quotesByIds.load(id)获取报价。一切正常。

但是,当我使用以下查询时:

query{
    authors{
    id
    name
    quotes{
      id
      author{
        name
      }
      quote
    }
  }
} 

DataBase请求如下:
  1。 Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author];
  2。 Executing (default): SELECT [id], [author_id], [quote] FROM [quote] AS [quote] WHERE [quote].[author_id] IN (1, 2, 3, 4, 5, 6, 7, 8);
  3。 Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 1;
  4。Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 2;
  5。Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 3;
  6。 Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 4;
  7。Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 4;
  8。Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 4;
  9。 Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 4;
  10。 Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 4;
  11。 Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 5;
  12。 Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 6;
  13。 Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] = 6;

第一个查询SELECT [id], [name], [last_name] FROM [author] AS [author];已经获取了所有作者,因此,不需要从 3到13 进行查询。

但是,此问题也可以通过实现DataLoader功能来解决。 之后,从 3到13 的查询将被批量处理为一个: Executing (default): SELECT [id], [name], [last_name] FROM [author] AS [author] WHERE [author].[id] IN (1,2,3,4,5,6);

有一种方法可以让解析程序知道根本不要运行此查询,因为作者姓名已经存在并且已经使用 Query 1 进行了提取。

0 个答案:

没有答案