【问题标题】:In GraphQL, how to control DB query by client query?在 GraphQL 中,如何通过客户端查询来控制 DB 查询?
【发布时间】:2019-07-26 17:42:39
【问题描述】:

这些天我学习使用 GraphQL。在我看来,要构建一个查询,我需要构建三个部分:

  1. 架构
type User{
  id String
  name String
  cars [Car!]!
}
type Car{
  id String
}
type Query{
  user(id: String): User
}
  1. 数据库查询功能
{
  user: async function ({id}) {
    const user = await DB.user.findOne({id});
    const userCars = await DB.car.find({userId: id});
    user.cars = userCars;
    return cars;
  }
}
  1. 客户端查询
{
  user (id: "1") {
    name
    cars {
      id
    }
  }
}

该查询返回用户的姓名和他的汽车。 DB 查询函数总是查询汽车。

但有时我只需要用户信息:

{
  user (id: "1") {
    name
  }
}

我不想查询汽车,所以我希望我的数据库查询功能可以自动选择是否查询汽车。

我该怎么做?

【问题讨论】:

    标签: graphql graphql-js


    【解决方案1】:

    最好避免将其全部压缩到一个解析器函数中。相反,为 Cars 创建一个单独的 ObjectType,它有自己的字段和自己的解析器函数。这样,只有在请求该字段时才会调用汽车查询。

    如果您使用的是 RDS,连接怪物和数据更响亮有助于优化查询性能。

    • Join Monster 依赖于生成一个大的连接查询,也解决了只从数据库中准确请求你需要的字段的问题
    • Cached and Batched SQL Data Source 在后台使用 facebook 的数据加载器 - 它不会解决要查询哪些字段的问题(尽管该示例使用 knex,这将使查询变得更容易),但它可以缓存和批处理您的查询

    【讨论】:

      【解决方案2】:

      我认为您正在研究从 GraphQL 查询到数据库查询的自动创建/映射。

      每个查询都是特定于数据库/项目的,因此您应该创建此映射。您可以使用 graphql-fields 包轻松做到这一点。

      包装中有复制粘贴的 WHY 部分:

      底层 REST api 只能返回基于查询参数的字段。

      {
        user {
          profile {
            firstName
          },
          id
        }
      }
      

      应该请求/api/user?fields=profile,id

      同时

      {
        user {
          email
        }
      }
      

      应该请求/api/user?fields=email 像这样实现你的解析方法:

      resolve(root, args, context, info) {
          const topLevelFields = Object.keys(graphqlFields(info));
          return fetch(`/api/user?fields=${topLevelFields.join(',')}`);
      }
      

      【讨论】:

      • 谢谢,这是一个更直接的解决方案。我查看了“信息”,但没有找到我需要的东西。这个模块很有用!
      【解决方案3】:

      GraphQL.js 将支持解析器函数的对象属性或方法;这在其页面Object Types 中进行了讨论。

      解决这个问题的一种方法是直接在返回的对象中插入一个匿名函数:

      {
        user: async function ({id}) {
          const user = await DB.user.findOne({id});
          user.cars = () => DB.car.find({userId: id});
          return cars;
        }
      }
      

      另一种方法是使用提供id 属性和(异步、惰性)cars 方法的类创建一个包装器对象;这方面的一些例子在GraphQL.js documentation 中。这种方法往往适用于大多数语言的大多数 GraphQL 实现。

      【讨论】:

      • 一个优雅的解决方案。节省我写“如果”的时间!
      猜你喜欢
      • 2019-07-26
      • 1970-01-01
      • 2020-06-14
      • 2018-02-18
      • 2013-05-05
      • 1970-01-01
      • 2022-06-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多