GraphQL学习与实践3(Mutations And Input Types)

GraphQL学习与实践3(Mutations And Input Types)

在上一节中留下了三个类型没有做讲述,分别为:接口、联合类型、输入类型

剩下的三个类型

接口类型
接口是一个抽象类型,它包含某些字段,而对象类型需要实现该接口,必须包含这些字段,接口用interface表示。
这里直接引用官网的例子进行举例:

interface Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
}

type Human implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  starships: [Starship]
  totalCredits: Int
}

type Droid implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  primaryFunction: String
}

两个类型都具备 Character 接口的所有字段,但也引入了其他的字段 totalCredits、starships 和 primaryFunction,这都属于特定的类型的角色。(即:如果返回的类型是Character,需要primaryFunction属性的话就会报错。)

联合类型
联合类型和接口十分相似,但是它并不指定类型之间的任何共同字段,用union表示。例如:

union SearchResult = Human | Droid | Starship

表示任何返回一个 SearchResult 类型的地方,都可能得到一个 Human、Droid 或者 Starship。或许简单点的来理解就是一个或的运算。

输入类型
为了更容易的传递复杂对象,特别是在变更(mutation)中特别有用,比如需要传递一整个对象的时候。input就是用在这个时候的关键字。例如:

input ReviewInput {
  stars: Int!
  commentary: String
}

变更
我们知道query在GraphQL中一个读的操作,那么想修改数据的时候,那又应该怎样呢?
在GraphQL中有这样一个约定来规范任何导致写入的操作都应该显式通过变更(mutation)来发送。
就如同查询一样,如果任何变更字段返回一个对象类型,你也能请求其嵌套字段。获取一个对象变更后的新状态也是十分有用的。我们来看看一个变更例子:

mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}

注意 createReview 字段如何返回了新建的 review 的 stars 和 commentary 字段。这在变更已有数据时特别有用,例如,当一个字段自增的时候,我们可以在一个请求中变更并查询这个字段的新值。
这个例子中,我们传递的 review 变量并非标量。它是一个输入对象类型,一种特殊的对象类型,可以作为参数传递。

Mutations And Input Types

在官网上就有这样的一个章节叫 Mutations And Input Types的。可以看得出一般mutations比较适合和Input类型一起使用,这里直接上官网的例子,新建一个test8-mutation.js文件,输入:

var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
// Construct a schema, using GraphQL schema language
var schema = buildSchema(` 
    input MessageInput { 
        content: String 
        author: String 
    } 
    type Message {
        id: ID! 
        content: String 
        author: String 
    } 
    type Query {
        getMessage(id: ID!): Message 
    } 
    type Mutation { 
        createMessage(input: MessageInput): Message 
        updateMessage(id: ID!, input: MessageInput): Message 
    } 
`
);
// If Message had any complex fields, we'd put them on this object.
class Message {
    constructor(id, { content, author }) {
        this.id = id;
        this.content = content;
        this.author = author;
    }
}
// Maps username to content
var fakeDatabase = {};
var root = {
    getMessage: function ({ id }) {
        if (!fakeDatabase[id]) {
            throw new Error('no message exists with id ' + id);
        }
        return new Message(id, fakeDatabase[id]);
    },
    createMessage: function ({ input }) {
        // Create a random id for our "database".
        var id = require('crypto').randomBytes(10).toString('hex');
        fakeDatabase[id] = input;
        return new Message(id, input);
    },
    updateMessage: function ({ id, input }) {
        if (!fakeDatabase[id]) {
            throw new Error('no message exists with id ' + id);
        }
        // This replaces all old data, but some apps might want partial update. 
        fakeDatabase[id] = input;
        return new Message(id, input);
    },
};
var app = express();
app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, }));
app.listen(4000, () => { console.log('Running a GraphQL API server at localhost:4000/graphql'); });

在上面的例子中,我们可以看出这个文件中定义了三个操作方法,一个是getMessage(获取信息)、一个是createMessage(创建信息)、一个是updateMessage(更新信息)。

执行node test8-mutation.js。打开浏览器(localhost:4000/graphql)的调试工具,输入:

mutation{
    createMessage(input:{
      author:"andy",
      content:"hope is a good thing",
    }){id}
}

这里是创建一个信息。如图:
在这里插入图片描述
然后查看信息类型对象的值是否创建成功了,注释点上面的创建信息的操作(ctrl+/),然后输入查询的操作,输入:

{
	getMessage(id:"20e68b77867e3a0dec9a") {
      id,
      author,
    }
}

如图:
在这里插入图片描述
这里的查询是引用了上面的创建操作之后的,如果id输入错误会是得到一个报错的返回的。然后,我们在执行修改操作,把author为“andy”修改为“andy123”,输入:

mutation{
  updateMessage(id:"20e68b77867e3a0dec9a",input:{
    author:"andy123",
    # content:"hope is a good thing",
  }){id,author}
}

得到的操作结果,如图:
在这里插入图片描述
从上图中,我们看到了此时内存中的数据已经被改变了。

然后,我们把上面用buildSchema的方式同样根据第二章节的做法进行用对象的形式改写一下,修改test8-mutation.js的文件:

var express = require('express');
var graphqlHTTP = require('express-graphql');
var graphql = require('graphql');
// Maps id to User object
var fakeDatabase = {};
// Define the User type

class Message {
    constructor(id, { content, author }) {
        this.id = id;
        this.content = content;
        this.author = author;
    }
}

var messageType = new graphql.GraphQLObjectType({
    name: 'Message',
    fields: {
        id: {
            type: graphql.GraphQLString
        },
        author: {
            type: graphql.GraphQLString
        },
        content: {
            type: graphql.GraphQLString
        },
    }
});

var messageInputType = new graphql.GraphQLInputObjectType({
    name: 'MessageInput',
    fields: {
        id: {
            type: graphql.GraphQLString
        },
        author: {
            type: graphql.GraphQLString
        },
        content: {
            type: graphql.GraphQLString
        },
    }
});

// Define the Query type
var queryType = new graphql.GraphQLObjectType({
    name: 'Query',
    fields: {
        getMessage: {
            type: messageType,
            args: {
                id: {
                    type: graphql.GraphQLString
                }
            },
            resolve: function (_, { id }) {
                if (!fakeDatabase[id]) {
                    throw new Error('no message exists with id ' + id);
                }
                return new Message(id, fakeDatabase[id]);
            }
        }
    }
});

var mutationType = new graphql.GraphQLObjectType({
    name: 'Mutation',
    fields: {
        createMessage: {
            type: messageType,
            args: {
                input: {
                    type: messageInputType
                }
            },
            resolve: function (_, { input }) {
                var id = require('crypto').randomBytes(10).toString('hex');
                fakeDatabase[id] = input;
                return new Message(id, input);
            }
        },
        updateMessage: {
            type: messageType,
            args: {
                id: {
                    type: graphql.GraphQLString
                },
                input: {
                    type: messageInputType
                }
            },
            resolve: function (_, { id, input }) {
                if (!fakeDatabase[id]) {
                    throw new Error('no message exists with id ' + id);
                }
                // This replaces all old data, but some apps might want partial update. 
                fakeDatabase[id] = input;
                return new Message(id, input);
            }
        }
    }
});

var schema = new graphql.GraphQLSchema({ query: queryType, mutation: mutationType });
var app = express();
app.use('/graphql', graphqlHTTP({
    schema: schema,
    graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');

如上所示,我们把buildSchema中的type的Message和input的MessageInput分别用GraphQLObjectType和GraphQLInputObjectType表示,同时把Query读操作和变更操作的Mutations也用GraphQLObjectType表示。在Query中只有getMessage一个区域,在Mutations中有createMessage和updateMessage两个区域。
然后同样的执行node test8-mutation.js。打开浏览器(localhost:4000/graphql)的调试工具,输入上面测试用例进行调试即可。

更多

GraphQL学习与实践1(入门介绍)
GraphQL学习与实践2(类型、传参与构造函数类型)
GraphQL学习与实践3(Mutations And Input Types)
GraphQL学习与实践4(模拟客户端请求)
GraphQL学习与实践5(连接数据库mongodb与mysql)

代码:
onsenOnly:https://github.com/onsenOnly/graphql-test

有缘请点颗星,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值