当 GraphQL 查询只需要返回对象的某些字段时,为啥 MySQL/Sequelize 会执行全选查询?

Posted

技术标签:

【中文标题】当 GraphQL 查询只需要返回对象的某些字段时,为啥 MySQL/Sequelize 会执行全选查询?【英文标题】:Why does MySQL/Sequelize perform full select queries when a GraphQL query only requires certain fields of an object to be returned?当 GraphQL 查询只需要返回对象的某些字段时,为什么 MySQL/Sequelize 会执行全选查询? 【发布时间】:2020-11-18 00:11:08 【问题描述】:

对于我的应用程序中的用户,我有一个类似这样的简单架构:

type Query 
  users: [User!]!


# The User ObjectType and Sequelize model.
type User implements UserI 
  id: ID!
  userName: String!
  firstName: String!
  lastName: String!
  email: String!
  createdAt: DateTime!
  updatedAt: DateTime!
  deletedAt: DateTime!

我的type-graphql 解析器实现了这个简单的代码来返回users 的列表:

@Resolver()
class UserResolver 
  @Query(() => [User])
  async users(): Promise<User[]> 
    return User.findAll();
  

当我执行这样的查询时:


  users 
    firstName
  

我预计等效的 mysql 查询会是这样的:SELECT firstName FROM users,但我可以看到 Sequelize 将查询记录为:

Executing (default): SELECT `id`, `userName`, `firstName`, `lastName`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `User` WHERE (`User`.`deletedAt` IS NULL);

现在,虽然一切正常(我可以在客户端获取所有用户及其数据),但我想知道如果 Sequelize 执行完整的属性选择,是否会对服务器端的性能造成影响?这是由于 Sequelize 还是仅仅由于 GraphQL 如何解析模型字段?我错过了一些选项吗?

【问题讨论】:

【参考方案1】:

我错过了一些选择吗?

您需要将 GraphQL 查询(请求)翻译成正确的 SQL 查询。只是调用findAll() 没有关于请求的任何信息,因此它正确地获取了完整的实体。

基本上,您需要将 GraphQL Resolve Info 解析为更易读的格式(例如使用https://www.npmjs.com/package/graphql-fields),然后为 TypeORM 构建一个select 选项(例如.findAll( select: ['id'] ))。

【讨论】:

以上是关于当 GraphQL 查询只需要返回对象的某些字段时,为啥 MySQL/Sequelize 会执行全选查询?的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL 使用 Introspection 时某些字段没有类型名称?

查询不会通过 GraphQL 从 DynamoDB 返回某些项目

当某些字段可以为 NULL 时,我可以使用对象作为 JPA 中条件查询的谓词吗?

GraphQL 嵌套文档在突变时返回 null

详解Python Graphql

在 graphQL 中提交对象数组作为查询变量