【问题标题】:Deep query to nested types in GraphQL return NULL对 GraphQL 中嵌套类型的深度查询返回 NULL
【发布时间】:2019-07-05 04:06:02
【问题描述】:

有一个奇怪的问题...

对嵌套类型的查询返回 null。

但是,如果我返回父类型中的任何内容 - 解析返回正确的结果

我的代码:

import { GraphQLList, GraphQLString, GraphQLID, GraphQLObjectType, GraphQLSchema } from 'graphql';
import AdminModel from '../models/Admin.model';

const AdminType = new GraphQLObjectType({
    name: 'AdminType',
    fields: {
        _id: { type: GraphQLID },
        login: { type: GraphQLString },
        password: { type: GraphQLString }
    }
});

const AdminRooteType = new GraphQLObjectType({
    name: 'AdminRooteType',
    fields: {
        getAdmins: {
            type: new GraphQLList(AdminType),
            resolve() {
                return AdminModel.find({})
            }
        }
    }
})

export default new GraphQLSchema({ 
    query: new GraphQLObjectType({
        name: 'RootQuery',
        fields: {
            admin: {
                type: AdminRooteType,
                resolve() {
                   // EMPTY RESOLVE - EMPTY RESULT
                }
            }
        }
    })
 });

查询:

{
  admin {
    getAdmins {
      login
    } 
  }
}

结果:

{
  "data": {
    "admin": null
  }
}

如果我在 RootQuery 的 admin 字段中更改了返回值:

import { GraphQLList, GraphQLString, GraphQLID, GraphQLObjectType, GraphQLSchema } from 'graphql';
import AdminModel from '../models/Admin.model';

const AdminType = new GraphQLObjectType({
    name: 'AdminType',
    fields: {
        _id: { type: GraphQLID },
        login: { type: GraphQLString },
        password: { type: GraphQLString }
    }
});

const AdminRooteType = new GraphQLObjectType({
    name: 'AdminRooteType',
    fields: {
        getAdmins: {
            type: new GraphQLList(AdminType),
            resolve() {
                return AdminModel.find({})
            }
        }
    }
})

export default new GraphQLSchema({ 
    query: new GraphQLObjectType({
        name: 'RootQuery',
        fields: {
            admin: {
                type: AdminRooteType,
                #resolve() {#
                    #// RETURN ANYTHING HERE:#
                  #  return 'foobar'#
                }
            }
        }
    })
 });

我得到了预期的结果:

{
  "data": {
    "admin": {
      "getAdmins": [
        {
          "login": "123"
        },
        {
          "login": "12asdf3"
        }
      ]
    }
  }
}

这个问题的正确解决方案是什么? (不使用虚拟值作为回报)

非常感谢!

【问题讨论】:

    标签: javascript node.js express graphql


    【解决方案1】:

    您看到的是预期的行为。想象一下,我们有一个带有一些字段的 User 类型:

    const UserType = new GraphQLObjectType({
      name: 'User',
      fields: {
        id: { type: GraphQLID },
        name: { type: GraphQLString },
      }
    })
    

    还有一种获取单个用户的方法:

    const QueryType = new GraphQLObjectType({
      name: 'Query',
      fields: {
        user: {
          type: AdminRooteType,
          resolve: () => getUser(),
        },
      },
    })
    

    如果getUser 返回一个表示User 的对象,则将调用所有字段的解析器(即User 类型上的idname

    当这些字段(以及它们可能拥有的任何子字段)解析时,您最终会得到一个用户对象,以便整个 user 字段返回。响应可能类似于:

    "data": {
      "user": {
        "id": 1,
        "name": "Maria",
        "comments": [
          {
            "id": 1,
            // and so on...
          }
        ]
      }
    }
    

    现在,考虑当找不到用户而我们返回 null 时会发生什么。我们的响应如下所示:

    "data": {
      "user": null
    }
    

    为 User 字段调用任何解析器是没有意义的。在这种情况下,您是否希望 API 仍返回 idname?如果是这样,这些字段将具有什么值?如果我们只返回一个空的idname,客户端如何将该对象与存在但确实具有idname 空值的用户区分开来?

    关键是,如果一个字段返回一个 GraphQLObjectType 并且它解析为 null,则不会调用 GraphQLObjectType 上的任何解析器。

    通过将 getAdmins 字段不必要地嵌套在另一个 GraphQLObjectType 中,您不得不在 admin 的解析器中返回某种对象。因此,您需要忍受这种情况,或者完全避免创建AdminRootType,而只需按照约定将getAdmins 字段直接放在您的查询类型上:

    const QueryType = new GraphQLObjectType({
      name: 'Query',
      fields: {
        getAdmins: {
          type: new GraphQLList(AdminType),
          resolve: () => AdminModel.find({}),
        },
      },
    })
    

    【讨论】:

    • 非常感谢,丹尼尔!主要思想是按类型(管理员、文章、订阅者等)对我的查询和突变进行分组。我认为这是让我的结构更清晰
    猜你喜欢
    • 2020-01-15
    • 2017-10-01
    • 2019-06-14
    • 2020-01-07
    • 2019-07-08
    • 2023-03-25
    • 1970-01-01
    • 2020-01-13
    相关资源
    最近更新 更多