如何在现有 GraphQL 服务器上添加根和查看器查询以支持中继
Posted
技术标签:
【中文标题】如何在现有 GraphQL 服务器上添加根和查看器查询以支持中继【英文标题】:How to add root and viewer queries on an existing GraphQL Server for Relay support 【发布时间】:2018-01-11 03:05:58 【问题描述】:我使用 GraphQL 已经有一段时间了,并且能够成功启动一个简单的 GraphQL 服务器。现在我正在尝试让它支持 Relay,这是我的最终目标,但在添加对根节点查询和查看器查询的支持时遇到了麻烦。
我确实了解节点和查看器的概念,但我并没有按照我构建代码的方式使其工作。这是我的代码,组织成单独的文件:
./graphql/User/types.js
import
GraphQLObjectType,
GraphQLInputObjectType,
GraphQLNonNull,
GraphQLID,
GraphQLList,
GraphQLString,
GraphQLInt,
GraphQLBoolean
from 'graphql';
import GraphQLLong from '../scalars';
import NodeInterface from '../interfaces';
const fields =
_id:
type: new GraphQLNonNull(GraphQLID)
,
email:
type: GraphQLString
,
firstName:
type: GraphQLString
,
lastName:
type: GraphQLString
,
jobTitle:
type: GraphQLString
,
phone:
type: GraphQLString
;
export const UserType = new GraphQLObjectType(
name: 'User',
description: 'User',
interface: NodeInterface,
fields: fields
)
./graphql/User/queries.js
import GraphQLNonNull, GraphQLID, GraphQLList from 'graphql';
import UserType, UserInputType from './types';
import UserModel from '../../models/User';
const User =
type: UserType,
description: 'Get single user',
args:
id:
name: 'id',
type: new GraphQLNonNull(GraphQLID)
,
resolve(root, params)
params.deleted = false;
return UserModel.find(params).exec();
const Users =
type: new GraphQLList(UserType),
description: 'Get all users',
resolve(root)
const companies = UserModel.find( deleted: false ).exec();
if (!companies)
throw new Error('Error getting users.')
return companies;
export default
User,
Users
./graphql/Company/types.js
import
GraphQLObjectType,
GraphQLInputObjectType,
GraphQLNonNull,
GraphQLID,
GraphQLList,
GraphQLString,
GraphQLInt,
GraphQLBoolean
from 'graphql';
import GraphQLLong from '../scalars';
import UserType from '../User/types';
import NodeInterface from '../interfaces';
import UserModel from '../../models/User';
const fields =
_id:
type: new GraphQLNonNull(GraphQLID)
,
name:
type: GraphQLString
,
ein:
type: GraphQLString
,
users:
type: new GraphQLList(UserType),
resolve(company)
const _id = company;
return UserModel.find( companyId: _id ).exec();
;
export const CompanyType = new GraphQLObjectType(
name: 'Company',
description: 'Company',
interface: NodeInterface,
fields: fields
)
./graphql/Company/queries.js
import GraphQLNonNull, GraphQLID, GraphQLList from 'graphql';
import CompanyType, CompanyInputType from './types';
import CompanyModel from '../../models/Company';
const Company =
type: CompanyType,
description: 'Get single company',
args:
id:
name: 'id',
type: new GraphQLNonNull(GraphQLID)
,
resolve(root, params)
params.deleted = false;
return CompanyModel.find(params).exec();
const Companies =
type: new GraphQLList(CompanyType),
description: 'Get all companies',
resolve(root)
const companies = CompanyModel.find( deleted: false ).exec();
if (!companies)
throw new Error('Error getting companies.')
return companies;
export default
Company,
Companies
./graphql/interfaces.js
import
GraphQLInterfaceType,
GraphQLNonNull,
GraphQLID
from 'graphql';
const NodeInterface = new GraphQLInterfaceType(
name: 'Node',
fields:
id:
type: new GraphQLNonNull(GraphQLID)
,
resolveType: (source) =>
return source.__type;
);
export default NodeInterface;
./graphql/schema.js
import GraphQLObjectType, GraphQLSchema from 'graphql';
import queries from './queries';
import mutations from './mutations';
export default new GraphQLSchema(
query: new GraphQLObjectType(
name: 'Query',
fields: queries
),
mutation: new GraphQLObjectType(
name: 'Mutation',
fields: mutations
)
);
./graphql/queries.js
import
GraphQLObjectType,
GraphQLNonNull,
GraphQLID
from 'graphql';
import NodeInterface from './interfaces';
import CompanyQueries from './Company/queries';
import UserQueries from './User/queries';
const RootQuery = new GraphQLObjectType(
name: 'RootQuery',
description: 'The root query',
fields:
viewer:
type: NodeInterface,
resolve(source, args, context)
return result: "VIEWER!" ;
,
node:
type: NodeInterface,
args:
id:
type: new GraphQLNonNull(GraphQLID)
,
resolve(source, args, context, info)
return result: "NODE QUERY" ;
);
export default
RootQuery,
...CompanyQueries,
...UserQueries
./server.js
import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import morgan from 'morgan';
import graphqlHTTP from 'express-graphql';
import schema from './graphql/schema';
// set up example server
const app = express();
app.set('port', (process.env.API_PORT || 3001));
// logger
app.use(morgan('dev'));
// parse body
app.use(bodyParser.json());
app.use('/graphql', graphqlHTTP(
schema: schema,
graphiql: true,
pretty: true
));
const mongoUri = process.env.MONGO_URI || 'mongodb://localhost/testdb';
mongoose.set('debug', true);
mongoose.connect(mongoUri,
useMongoClient: true,
);
export default app;
未将 RootQuery 添加到架构中。事实上我得到了这个错误:
Error: Query.RootQuery field type must be Output Type but got: undefined.
从概念上讲,我不知道如何修复此代码:
a) 我不知道如何将该 RootQuery 添加到我的查询中,并且我不知道是否需要将其他查询保留到我的服务器(因为 Relay 基本上依赖于节点查询)。
b) 我也看不到我的 RootQuery 将如何发现对象类型并将其返回到 return source.__type
。我已经添加了那段代码,但我不知道给定类型将如何或在何处填充此字段。
虽然我对 GraphQL 有点了解,但似乎我还没有关于如何构建 Relay 所需的根查询的基础知识(不谈论分页器,但这是我解决后的下一步那个)。
【问题讨论】:
你能显示 scalars.js 吗? 【参考方案1】:问题似乎是
import queries from './queries';
new GraphQLObjectType(
name: 'Query',
fields: queries
),
const RootQuery = new GraphQLObjectType(
…
);
export default
RootQuery,
…
;
您作为Query
类型的字段传递的queries
是类型对象,而不是字段配置对象。它们缺少 type
和 resolve
属性,因为错误消息提示。
【讨论】:
以上是关于如何在现有 GraphQL 服务器上添加根和查看器查询以支持中继的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Apollo GraphQL Server 中添加字段解析器