本文属使用Prisma构建GraphQL服务系列。
Prisma API提供:
- 简单突变:创建,更新,插入和删除特定对象类型的单个节点
- 批量突变:更新和删除某个模型的许多节点
- 关系突变:连接,断开,创建,更新和上传跨关系的节点
通常,服务的Prisma API是基于其数据模型生成的。要探索Prisma API中的操作,可以使用GraphQL Playground。
在下文中,我们将探索基于此数据模型的基于Prisma服务的示例查询:
type Post {
id: ID! @unique
title: String!
published: Boolean!
author: User!
}
type User {
id: ID! @unique
age: Int
email: String! @unique
name: String!
posts: [Post!]!
}
对象突变(Object mutations)
我们可以使用模型突变来修改某个模型的单个节点。
创建节点(Creating nodes)
在这里,我们使用createUser
突变来创建一个新用户:
# Create a new user
mutation {
createUser(
data: {
age: 42
email: "[email protected]"
name: "Zeus"
}
) {
id
name
}
}
注意:无默认值的必填字段,需要在数据输入对象中指定。
修改节点(Updating nodes)
我们可以使用updateUser更改电子邮件和名称。请注意,我们正在使用where
参数选择要更新的节点:
mutation {
updateUser(
data: {
email: "[email protected]"
name: "Zeus2"
}
where: {
email: "[email protected]"
}
) {
id
name
}
}
修改插入(Upserting nodes)
当我们想要更新现有的节点,或者在单个突变中创建一个新节点时,我们可以使用upsert突变。
在这里,我们使用upsertUser
通过某个email
更新User
,或者如果具有该email
的User
尚不存在,就创建一个新User
:
# Upsert a user
mutation {
upsertUser(
where: {
email: "[email protected]"
}
create: {
email: "[email protected]"
age: 42
name: "Zeus"
}
update: {
name: "Another Zeus"
}
) {
name
}
}
注:
create
和update
与createUser
和updateUser
突变中的数据对象具有相同的类型。
删除节点(Deleting nodes)
要删除节点,我们所要做的就是使用delete
突变删除选择的节点。
在这里,我们使用deleteUser
突变,通过它的id
删除一个User
:
mutation {
deleteUser(where: {
id: "cjcdi63l20adx0146vg20j1ck"
}) {
id
name
email
}
}
由于email
用@unique
指令标记,我们也可以通过他们的email
选择(并因此删除)User
节点:
mutation {
deleteUser(where: {
email: "cjcdi63l20adx0146vg20j1ck"
}) {
id
name
email
}
}
嵌套突变(Nested mutations)
我们可以使用create
和update
模型突变来同时修改关系中的节点。这被称为嵌套的突变,并被事务执行。
概述(Overview)
存在几个嵌套突变参数:
create
update
upsert
delete
connect
disconnect
它们的可用性和确切的行为取决于以下两个参数:
- 父突变类型
-
create
突变 -
update
突变 -
upsert
突变
-
- 关系的类型
- 可选的一对一关系
- 必须的一对一关系
- 一对多关系
例如:
- 创建突变只会暴露嵌套的
create
和connect
突变 - 更新突变暴露
update
,upsert
突变为必需的一对一关系
栗子(Examples)
在这一点上,我们不提供所有可能的场景,而是提供一个例子列表。
建议使用GraphQL Playground查看不同嵌套突变的行为。
创建并连接相关节点
我们可以在嵌套的输入对象字段中使用连接操作来连接到一个或多个相关节点。
在这里,我们正在创建一个新的Post
并通过唯一的email
字段connect
到现有的author
。在这种情况下,connect
为节点选择提供了一种方法:
# Create a post and connect it to an author
mutation {
createPost(data: {
title: "This is a draft"
published: false
author: {
connect: {
email: "[email protected]"
}
}
}) {
id
author {
name
}
}
}
如果我们在author
中提供create
参数而不是connect
,我们将创建一个相关author
并同时connect
到它,而不是connect
到现有的author
。
在创建User
而不是Post
时,我们实际上可以同时create
并connect
到多个Post
节点,因为User
具有多对多的Post
。
在这里,我们正在create
一个新User
并直接将其连接到几个新的和现有的Post
节点:
# Create a user, create and connect new posts, and connect to existing posts
mutation {
createUser(
data: {
email: "[email protected]"
name: "Zeus"
age: 42
posts: {
create: [{
published: true
title: "First blog post"
}, {
published: true
title: "Second blog post"
}]
connect: [{
id: "cjcdi63j80adw0146z7r59bn5"
}, {
id: "cjcdi63l80ady014658ud1u02"
}]
}
}
) {
id
posts {
id
}
}
}
更新(updating)和更新插入(upserting)相关节点
更新节点时,可以同时更新一个或多个相关节点。
mutation {
updateUser(
data: {
posts: {
update: [{
where: {
id: "cjcf1cj0r017z014605713ym0"
}
data: {
title: "Hello World"
}
}]
}
}
where: {
id: "cjcf1cj0c017y01461c6enbfe"
}
) {
id
}
}
请注意,
update
接受包含适合updatePost
突变的where
和data
字段的对象列表。
嵌套更新插入(upserting)类似:
mutation {
updatePost(
where: {
id: "cjcf1cj0r017z014605713ym0"
}
data: {
author: {
upsert: {
where: {
id: "cjcf1cj0c017y01461c6enbfe"
}
update: {
email: "[email protected]"
name: "Zeus2"
}
create: {
email: "[email protected]"
name: "Zeus"
}
}
}
}
) {
id
}
}
删除相关节点
更新节点时,可以同时删除一个或多个相关节点。在这种情况下,delete
提供了一种节点选择方式:
mutation {
updateUser(
data: {
posts: {
delete: [{
id: "cjcf1cj0u01800146jii8h8ch"
}, {
id: "cjcf1cj0u01810146m84cnt34"
}]
}
}
where: {
id: "cjcf1cj0c017y01461c6enbfe"
}
) {
id
}
}
标量列表突变(Scalar list mutations)
当一个对象类型有一个标量列表作为其类型的字段时,有许多特殊的突变可用。
在以下数据模型中,User
类型有三个这样的字段:
type User {
id: ID! @unique
scores: [Int!]! # scalar list for integers
friends: [String!]! # scalar list for strings
coinFlips: [Boolean!]! # scalar list for booleans
}
创建节点(Creating nodes)
创建类型为User
的新节点时,可以使用set
为每个标量列表字段提供一个值列表。
例如:
mutation {
createUser(data: {
scores: { set: [1, 2, 3] }
friends: { set: ["Sarah", "Jane"] }
throws: { set: [false, false] }
}) {
id
}
}
更新节点(Updating nodes)
更新User
类型的现有节点时,可以在标量列表字段上执行一些附加操作:
-
set
:用一个全新的列表覆盖现有列表。 -
push
(coming soon):在列表中的任何位置添加一个或多个元素。 -
pop
(coming soon):从列表的开头或结尾删除一个或多个元素。 -
remove
(coming soon):删除列表中与给定过滤器匹配的所有元素。
注意:
push
,pop
和remove
尚未实现。如果你真的好奇这些将会是什么样子,你可以在相应的规范(specification)中看到预览。
set
每个标量列表字段都会在update
突变中使用具有set
字段的对象。该字段的值是单个值或相应标量类型的列表。
栗子:将现有User
节点的scores
设置为[1]:
mutation {
updateUser(
where: {
id: "cjd4lfdyww0h00144zst9alur"
}
data: {
scores: {
set: 1
}
}
) {
id
}
}
将现有User
节点的scores
设置为[10,20,30]:
mutation {
updateUser(
where: {
id: "cjd4lfdyww0h00144zst9alur"
}
data: {
scores: {
set: [10,20,30]
}
}
) {
id
}
}
批量突变(Batch Mutations)
批处理突变可用于一次更新或删除多个节点。返回的数据只包含受影响节点的数量。
为了更新许多节点,可以使用where
参数选择受影响的节点,同时用data
指定新值。所有节点将更新为相同的值。
请注意,批量突变不会触发订阅事件!
在这里,我们正在发布在2017年创建的所有未发布的Post
节点:
mutation {
updateManyPosts(
where: {
createdAt_gte: "2017"
createdAt_lt: "2018"
published: false
}
data: {
published: true
}
) {
count
}
}
在这里,我们删除某个作者的所有未发布的Post节点:
mutation {
deleteManyPosts(
where: {
published: false
author: {
name: "Zeus"
}
}
) {
count
}
}