Prisma API:突变(Mutations)

本文属使用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: "zeus@example.com"
      name: "Zeus"
    }
  ) {
    id
    name
  }
}

注意:无默认值的必填字段,需要在数据输入对象中指定。

修改节点(Updating nodes)

我们可以使用updateUser更改电子邮件和名称。请注意,我们正在使用where参数选择要更新的节点:

mutation {
  updateUser(
    data: {
      email: "zeus2@example.com"
      name: "Zeus2"
    }
    where: {
      email: "zeus@example.com"
    }
  ) {
    id
    name
  }
}

修改插入(Upserting nodes)

当我们想要更新现有的节点,或者在单个突变中创建一个新节点时,我们可以使用upsert突变。

在这里,我们使用upsertUser通过某个email更新User,或者如果具有该emailUser尚不存在,就创建一个新User

# Upsert a user
mutation {
  upsertUser(
    where: {
      email: "zeus@example.com"
    }
    create: {
      email: "zeus@example.com"
      age: 42
      name: "Zeus"
    }
    update: {
      name: "Another Zeus"
    }
  ) {
    name
  }
}

注:createupdatecreateUserupdateUser突变中的数据对象具有相同的类型。

删除节点(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)

我们可以使用createupdate模型突变来同时修改关系中的节点。这被称为嵌套的突变,并被事务执行。

概述(Overview)

存在几个嵌套突变参数:

  • create
  • update
  • upsert
  • delete
  • connect
  • disconnect

它们的可用性和确切的行为取决于以下两个参数:

  • 父突变类型
    • create突变
    • update突变
    • upsert突变
  • 关系的类型
    • 可选的一对一关系
    • 必须的一对一关系
    • 一对多关系

例如:

  • 创建突变只会暴露嵌套的createconnect突变
  • 更新突变暴露updateupsert突变为必需的一对一关系

栗子(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: "zeus@example.com"
      }
    }
  }) {
    id
    author {
      name
    }
  }
}

如果我们在author中提供create参数而不是connect,我们将创建一个相关author并同时connect到它,而不是connect到现有的author

在创建User而不是Post时,我们实际上可以同时createconnect到多个Post节点,因为User具有多对多的Post

在这里,我们正在create一个新User并直接将其连接到几个新的和现有的Post节点:

# Create a user, create and connect new posts, and connect to existing posts
mutation {
  createUser(
    data: {
      email: "zeus@example.com"
      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突变的wheredata字段的对象列表。

嵌套更新插入(upserting)类似:

mutation {
  updatePost(
    where: {
      id: "cjcf1cj0r017z014605713ym0"
    }
    data: {
      author: {
        upsert: {
          where: {
            id: "cjcf1cj0c017y01461c6enbfe"
          }
          update: {
            email: "zeus2@example.com"
            name: "Zeus2"
          }
          create: {
            email: "zeus@example.com"
            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):删除列表中与给定过滤器匹配的所有元素。

注意:pushpopremove尚未实现。如果你真的好奇这些将会是什么样子,你可以在相应的规范(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
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容

  • 一天我们去吃火锅,先去了超级市场买了一些火锅用的酱料,又去了一个小超市买了一点涮羊肉。 爸爸先下车去买羊肉的啦,而...
    幸福之家_871c阅读 175评论 0 0
  • 大家说生活让我们变得坚强,与其说坚强的隐忍不能说无奈的妥协。 如果你的老婆很矫情,很自我,不顺心就...
    4点半的恩赐阅读 353评论 0 0
  • 经常觉得自己日子过得浑浑噩噩,不知道该干什么。感觉自己人生没有目标,不知道该朝哪个方向去努力,怎么破?其实,这就是...
    何丽娟_8c58阅读 145评论 1 3
  • #人与动物的区别最大的两点(在目前我们也发现这其中还有很多其他复杂因素,等待考究),就是语言和性行为。 #在人的1...
    奥利奥睡不醒阅读 561评论 0 3