对GraphQL中的嵌套类型进行深度查询将返回NULL

时间:2019-02-11 15:54:46

标签: javascript node.js express graphql

有一个奇怪的问题...

查询嵌套类型返回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"
        }
      ]
    }
  }
}

该问题的正确解决方案是什么? (不返回任何虚拟值)

非常感谢!

1 个答案:

答案 0 :(得分:0)

您看到的是预期的行为。假设我们有一个带有某些字段的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的对象,则将调用所有字段(即id类型的nameUser的解析器

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

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

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

"data": {
  "user": null
}

为“用户”字段调用任何解析器都没有道理。在这种情况下,您是否希望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({}),
    },
  },
})