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: "[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,或者如果具有该emailUser尚不存在,就创建一个新User

# Upsert a user
mutation {
  upsertUser(
    where: {
      email: "[email protected]"
    }
    create: {
      email: "[email protected]"
      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: "[email protected]"
      }
    }
  }) {
    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: "[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突变的wheredata字段的对象列表。

嵌套更新插入(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):删除列表中与给定过滤器匹配的所有元素。

注意: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
  }
}

你可能感兴趣的:(Prisma API:突变(Mutations))