如何在现有 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 是类型对象,而不是字段配置对象。它们缺少 typeresolve 属性,因为错误消息提示。

【讨论】:

以上是关于如何在现有 GraphQL 服务器上添加根和查看器查询以支持中继的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Apollo GraphQL Server 中添加字段解析器

如何在graphql中将装饰器添加到args参数

解析器中的 AppSync GraphQL 变异服务器逻辑

如何在 GraphQL 解析器中添加用于缓存的 redis 客户端

在 REST API 周围添加 graphql 包装器?

如何在两个字段 prisma-graphql 中使用相同的生成 ID