Prisma client是一个自动生成的库,可连接到你的Prisma service。在this文章中了解更多信息。

使用[Prisma CLI]prisma generate命令自动生成Prisma client。 一个Prisma client连接到一个Prisma service。

prisma generate读取prisma.yml中generate属性下指定的信息。

generate根属性接受一个对象列表。 每个对象都有两个字段:

  • generator: #生成Prisma client的编程语言。    - 可选的值:typescript-client, javascript-client, flow-client, go-client.    - 即将推出:reason
  • output:应存储Prisma client的文件的路径和名称。

例如,我们看下面的prisma.yml:


datamodel: datamodel.prisma
endpoint: http://localhost:4000
generate:
  - generator: typescript-client
    output: ./prisma-client/

在prisma.yml所在的目录中运行prisma generate会在TypeScript中生成一个Prisma client,并将其存储在名为prisma.ts的文件中。

generator也接受graphql-schema作为值。 这将通过introspection查询下载Prisma API的GraphQL schema。

generate接受一个对象列表时,你也可以同时生成多个文件:


datamodel: datamodel.prisma
endpoint: http://localhost:4466
secret: mysecret42
generate:
  - generator: typescript-client
    output: ./prisma-client-ts/
  - generator: javascript-client
    output: ./prisma-client-js/
  - generator: go-client
    output: ./prisma-client-go/
  - generator: flow-client
    output: ./prisma-client-flow/
  - generator: graphql-schema
    output: ./graphql-schema/

假设Prisma service的数据模型定义如下:


type Link {
  id: ID! @unique
  createdAt: DateTime!
  description: String!
  url: String!
  postedBy: User
  votes: [Vote!]!
}
type User {
  id: ID! @unique
  name: String!
  email: String! @unique
  password: String!
  links: [Link!]!
  votes: [Vote!]!
}
type Vote {
  id: ID! @unique
  link: Link!
  user: User!
}

你可以在你电脑本地或者此处查看生成的文件的代码:

生成的Prisma client已经知道在生成时prisma.yml中指定的endpointsecret

Prisma构造函数用于创建Prisma client的新实例。


constructor(options: BasePrismaOptions)

BasePrismaOptions具有以下属性(都是可选的):

  • endpoint: string:Prisma service的端点。 如果未提供,则client将默认使用在生成client时在prisma.yml中指定的"端点"。
  • secret: string:保护Prisma serviceAPI的密码。 如果未提供,client将默认使用在生成client时在prisma.yml中指定的secret
  • debug: boolean:如果设置为true,Prisma client上每个方法的调用都会打印发送到Prisma API的GraphQL查询到控制台。 默认值:false
  • fragmentReplacements: FragmentReplacement []:将应用于发送到Prisma API的每个Query/Mutation/Subscriptions的GraphQL片段列表。

使用client generate时在prisma.yml中指定的endpointsecret的默认值:


const prisma = new Prisma({})

覆盖默认值:


const prisma = new Prisma({ 
  endpoint: "http://localhost:4466/hello-world/dev",
  secret: "mysecret42",
})

Prisma构造函数用于创建Prisma client的新实例。


constructor(options: BasePrismaOptions)

BasePrismaOptions具有以下属性(都是可选的):

  • endpoint:string:Prisma service的端点。 如果未提供,则client将默认使用在生成client时在prisma.yml中指定的"端点"。
  • secret:string:保护Prisma serviceAPI的密码。 如果未提供,client将默认使用在生成client时在prisma.yml中指定的secret
  • debug:boolean:如果设置为true,Prisma client上每个方法的调用都会打印发送到Prisma API的GraphQL查询到控制台。 默认值:false
  • fragmentReplacements:FragmentReplacement []:将应用于发送到Prisma API的每个Query/Mutation/Subscriptions的GraphQL片段列表。

使用client生成时在prisma.yml中指定的endpointsecret的默认值:


const prisma = new Prisma({})

覆盖默认值:


const prisma = new Prisma({ 
  endpoint: "http://localhost:4466/hello-world/dev",
  secret: "mysecret42",
})

Prisma构造函数用于创建Prisma client的新实例。


New(options PrismaOptions) Client

PrismaOptions具有以下属性(都是可选的):

  • endpoint:string:Prisma service的端点。 如果未提供,则client将默认使用在生成client时在prisma.yml中指定的"端点"。
  • debug:boolean:如果设置为true,Prisma client上每个方法的调用都会打印发送到Prisma API的GraphQL查询到控制台。 默认值:false

使用client生成时在prisma.yml中指定的endpointsecret的默认值:


db := prisma.New(nil)

覆盖默认值:


client := prisma.New(&prisma.PrismaOptions{
  Endpoint: "http://localhost:4466/hello-world/dev",
  Debug: true,
})

Prisma client基于Prisma API的GraphQL schema定义生成操作。对于reading数据,它基本上复制你Prisma service中的GraphQL Query

对于此页面,我们假设你的Prisma API基于以下datamodel:


type Link {
  id: ID! @unique
  createdAt: DateTime!
  description: String!
  url: String!
  postedBy: User
  votes: [Vote!]!
}
type User {
  id: ID! @unique
  name: String!
  email: String! @unique
  password: String!
  links: [Link!]!
  votes: [Vote!]!
}
type Vote {
  id: ID! @unique
  link: Link!
  user: User!
}
  • 你可以查看API生成的GraphQL schema这里
  • 你可以查看生成的JavaScript client此处

每当使用Prisma client查询模型时,都会获取该模型的所有字段。无论是查询单个对象还是对象列表,都是如此。

例如,以下查询返回单个"User"的所有标量字段:


const user = await prisma.user({ email: "bob@prisma.io" })

在这种情况下,返回的user对象将具有四个属性(对应于User模型的标量字段):idnameemailpassword

linksvotes字段都是relation fields,因此不包含在查询中。

以下是获取所有User对象列表的示例:


const users = await prisma.users()

与前面的查询类似,users数组中的每个对象只有标量和无关系字段。

对于datamodel中的每个模型类型,在Prisma clientAPI中生成一种方法,允许获取该模型的单个对象。 该方法以类型命名,但以小写字符开头。 对于上面的示例数据模型,获取单个"User","Link"和"Vote"对象的三种方法称为"user","link"和"vote"。

这些函数的输入是一个对象,它具有模型的任何 唯一字段作为属性。 这意味着,对于所有三种方法,都接受id字段(因为相应的模型每个都有一个注释为@uniqueid字段)。 user方法的输入对象另外有一个email字段可以来查询。

  • 查看Link的"where"类型here
  • 查看User的"where"类型here
  • 查看Vote的"where"类型here

以下所有例子中,第一段代码为resolvers中的代码,第二段是playground中的操作

通过其id获取单个投票:


const vote = await prisma.vote({ id: "cjlgpyueg001o0a239d3i07ao" })

# generated query
query {
  vote(where: {
    id: "cjlgpyueg001o0a239d3i07ao"
  }) {
    id
  }
}

通过email获取单个用户:


const user = await prisma.user({ email: "alice@prisma.io" })

# generated query
query {
  user(where: {
    email: "alice@prisma.io"
  }) {
    id
  }
}

对于datamodel中的每个模型类型,在Prisma clientAPI中生成一个方法,允许获取这些模型对象的列表。 该方法以模型命名,但以小写字符开头并使用复数形式。 对于上面的示例数据模型,获取"User","Link"和"Vote"模型列表的三种方法称为"users","links"和"votes"。

这些函数的输入参数是一个具有以下属性的对象:

获取所有links:


const links = await prisma.links()

# generated query
query {
  links {
    id
    createdAt
    url
    description
  }
}

获取users列表:


const users = await prisma.users()

query {
  links {
    id
    createdAt
    url
    description
  }
}

Prisma client基于fluent API来查询数据图中的关系。这意味着你可以简单地链式调用你的方法来返回模型的关系属性。

注意

这仅在检索单个对象时才有可能,而不是用于列表。这意味着你无法查询列表中返回的对象的关系字段,例如:


//不可能
const result = await prisma
  .users()
  .links()

在这个例子中,users()已经返回一个列表,因此不可能查询列表中每个用户对象的links关系。

Query查询单个user的所有链接:


const linksByUser = await prisma
  .user({ email: "alice@prisma.io" })
  .links()

query {
  user(where: {
    email: "alice@prisma.io"
  }) {
    links {
      id
      createdAt
      description
      url
    }
  }
}

 查询某个user所做的所有投票:


const votesByUser = await prisma
  .user({ email: "alice@prisma.io" })
  .votes()

query {
  user(where: {
    email: "alice@prisma.io"
  }) {
    votes {
      id
    }
  }
}

你可以使用$fragment API功能(基于GraphQL)指定要检索的字段,而不是查询模型的所有标量字段(这是默认行为)。这对于排除大量不需要的字段(如BLOB值或大字符串)或检索关系很有用。

获取用户的nameemail以及相关linksdescriptionurl:


const fragment = `
fragment UserWithLinks on User {
  name
  email
  links {
    description
    url
  }
}
`
const userWithPosts = await prisma.users().$fragment(fragment)

query {
  users {
    ...UserWithLinks
  }
}
fragment UserWithLinks on User {
  name
  email
  links {
    description
    url
  }
}

Basic过滤器允许你指定某些条件来约束应在列表中返回哪些对象。过滤器在输入参数的where对象中指定,任何列表查询都接受该对象。

where对象的类型取决于生成它的模型。

查看LinkUserVotewhere类型

  • 查看Link的"where"类型here
  • 查看User的"where"类型here
  • 查看Vote的"where"类型here

也可以使用ANDOR字段组合多个过滤器。

找到名称中包含"A"的用户:


const usersWithAInName = await prisma
  .users({
    where: {
      name_contains: "A"
    }
  })

query {
  users(where: {
      name_contains: "A"
  }) {
    id
    name
    email
    password
  }
}

使用自动完成功能来探索过滤系统

查询称为"Alice"或"Bob`的用户:


const usersCalledAliceOrBob = await prisma
  .users({
    where: {
      name_in: ["Alice", "Bob"]
    }
  })

query {
  users(where: {
    name_in: ["Alice", "Bob"]
  }) {
    id
    name
    email
    password
  }
}

获取2018年12月24日之前创建的链接:


const linksBeforeChristmas = await prisma
  .links({
    where: {
      createdAt_lt: "2018-12-24" 
    }
  })

query {
  links(where: {
    createdAt_lt: "2018-12-24" 
  }) {
    id
    createdAt
    description
    url
  }
}

Prisma client API中的日期和时间遵循ISO 8601标准,该标准通常具有以下形式:YYYY-MM-DDThh:mm:ss

查询在description中有prisma graphql的链接并且是在2018年创建的:


const filteredLinks = await prisma
  .links({
    where: {
      AND: [
        {
          OR: [{
            description_contains: "graphql",
          }, {
            description_contains: "prisma",
          }]
        }, 
        {
          AND: [{
            createdAt_gt: "2017"
          }, {
            createdAt_lt: "2019"
          }]
        }
      ],
    }
  })

query {
  links(where: {
    OR: [{
      description_contains: "graphql",
    }, {
      description_contains: "prisma",
    }]
    AND: [{ 
      createdAt_lt: "2019"
    }, { 
      createdAt_gt: "2017" 
    }]
  }) {
    id
    description
  }
}

实际上可以省略AND过滤器,因为默认情况下使用logical and组合了多个过滤条件。这意味着上面的过滤器也可以表示如下:


const filteredLinks = await prisma
  .links({
    where: {
      OR: [{
        description_contains: "graphql"
      }, {
        description_contains: "prisma"
      }],
      createdAt_gt: "2017",
      createdAt_lt: "2019"
    }
  })

query {
  links(where: {
    OR: [{
      description_contains: "graphql",
    }, {
      description_contains: "prisma",
    }],
    createdAt_lt: "2019",
    createdAt_gt: "2017" 
  }) {
    id
    createdAt
    description
    url
  }
}

关系过滤器可用于约束关系列表字段上的返回对象。用于过滤的类型与基本过滤器相同,唯一的区别是过滤器不应用于方法调用的第一级,而是在第二级查询关系时。


const linksByUserBeforeChristmas = await prisma
  .user({ email: "alice@prisma.io" })
  .links({
    where: {
      createdAt_lt: "2017-12-24" 
    }
  })

query {
 user(where: {
  email: "alice@prisma.io"
 }) {
    links(where: {
      createdAt_lt: "2017-12-24" 
    }) {
      id
      createdAt
      description
      url
  }
 }
}

查询模型对象列表时,可以按该模型类型的任何标量字段对列表进行排序。因此,每个生成的查询模型列表的方法都接受其输入对象上的orderBy字段。

orderBy字段的类型取决于生成它的模型的标量字段。

查看linkuserVoteorderBy类型

  • 查看linkorderBy类型here
  • 查看userorderBy类型here
  • 查看VoteorderBy类型here

_按创建日期(升序)_links:


const sortedLinks = prisma
  .links({
    orderBy: "createdAt_ASC"
  })

query {
  links(orderBy: createdAt_ASC) {
    id
    createdAt
    description
    url
  }
}

按字母顺序排序用户名(降序):


const sortedUsers = prisma
  .users({
    orderBy: "name_DESC"
  })

query {
  users(orderBy: name_DESC) {
    id
    name
    email
    password
  }
}

查询模型对象列表时,可以通过提供分页参数来获取该列表的部分信息。常在feed流中使用。

你可以在对象中向前或从后往前并提供可选的起始对象:

  • 从前往后,使用first;用after指定一个起始对象。
  • 从后往前,请使用last;用before指定一个起始对象。

不能firstbeforelastafter结合起来。如果你在查询中这样做,before/after将被忽略,实际上只应用firstlast(在列表的开头或结尾,取决于你使用的是哪个) 。

请注意,你可以在没有错误消息的情况下查询比实际存在的对象更多的对象。

你还可以通过提供skip参数跳过任意方向的任意数量的对象:

  • 当使用first时,skip会跳过列表开头的对象。
  • 当使用last时,skip跳过列表末尾的对象。

对于以下示例,我们假设一个正好包含30个对象的列表:

查询前3个链接(从前往后):


const links = await prisma
  .links({
    first: 3
  })

query {
  links(first: 3) {
    id
    createdAt
    description
    url
  }
}

查询从位置6到位置10的对象(从前往后):


const links = await prisma
  .links({
    first: 5, 
    skip: 5
  })

query {
  links(
    first: 5 
    skip: 5
  ) {
    id
    createdAt
    description
    url
  }
}

查询最后3个对象(从后往前):


const links = await prisma
  .links({
    last: 3
  })

query {
  links(last: 3) {
    id
    createdAt
    description
    url
  }
}

查询从第21位到第27位的对象(从后往前):


const links = await prisma
  .links({
    last: 7,
    skip: 3
  })

query {
  links(
    last: 7
    skip: 3
  ) {
    id
    createdAt
    description
    url
  }
}

使用cixnen24p33lo0143bexvr52n作为id查询对象之后的前3个对象:


const links = await prisma
  .links({
    first: 3,
    after: "cixnen24p33lo0143bexvr52n"
  })

query {
  links(
    first: 3
    after: "cixnen24p33lo0143bexvr52n"
  ) {
    id
    createdAt
    description
    url
  }
}

使用cixnen24p33lo0143bexvr52n作为id跳过3条数据查询后面的5个对象:


const links = await prisma
  .links({
    first: 5,
    after: "cixnen24p33lo0143bexvr52n",
    skip: 3
  })

query {
  links(
    first: 5
    after: "cixnen24p33lo0143bexvr52n"
    skip: 3
  ) {
    id
    createdAt
    description
    url
  }
}

使用cixnen24p33lo0143bexvr52n作为id查询对象之前的最后5个对象:


const links = await prisma
  .links({
    last: 5,
    before: "cixnen24p33lo0143bexvr52n"
  })

query {
  links(
    last: 5
    before: "cixnen24p33lo0143bexvr52n"
  ) {
    id
    createdAt
    description
    url
  }
}

查询节点之前的最后3个节点,其中cixnen24p33lo0143bexvr52n为id并跳过5个:


const links = await prisma
  .links({
    last: 3,
    before: "cixnen24p33lo0143bexvr52n",
    skip: 5
  })

query {
  links(
    last: 3 
    before: "cixnen24p33lo0143bexvr52n"
    skip: 5
  ) {
    id
    createdAt
    description
    url
  }
}

你可以通过[Connection查询]提交聚合查询。支持以下聚合功能:

  • count:计算列表中的对象数
  • avg(即将推出):计算数字列表的平均值。
  • median(即将推出):计算数字列表的中位数。
  • max(即将推出):返回数字列表中最大的元素。
  • min(即将推出):返回数字列表中的最小元素。
  • sum(即将推出):计算数字列表的总和。

请参阅thisGitHub问题以了解有关即将推出的聚合功能的更多信息。

Count链接对象的数量:


const linkCount = await prisma
  .linksConnection()
  .aggregate()
  .count()

query {
  linksConnection {
    aggregate {
      count
    }
  }
}

对于前面创建的的数据模型,每个模型类型生成了写入数据六种方法。这些在GraphQL schema,例如用于User模型中的Mutation而得到:

  • createUser:创建一个新的User记录在数据库中

  • updateUser:更新现有User记录在数据库中

  • deleteUser:从数据库中删除现有的User记录

  • upsertUser:更新现有的或在数据库中创建一个新的User纪录

  • updateManyUsers:更新许多现有的User数据库中的记录

  • deleteManyUsers:从数据库中删除现有的许多User记录

  • 你可以查看一下生成GraphQL schema的API 这里

  • 你可以查看要生成的JavaScript client这里

这些方法中的一个的每个调用被作为[事务]执行,这意味着它要么保证完全成功,或者如果它只是部分地失败但要被全部取消而回到原先状态,所以不必担心数据一致性。

当在数据库中创建新的记录,create方法需要用一个输入对象包裹起来所有数据。它还提供了一种用于模型创建关系数据,这可以通过使用嵌套对象写入来提供。

每个方法调用的返回包含刚刚创建的模型的所有字段。

create新用户:


const newUser = await prisma
  .createUser({
    name: "Alice",
    email: "alice@prisma.io",
    password: "IlikeTurtles"
  })

# generated mutation
mutation {
  createUser(data: {
    name: "Alice"
    email: "alice@prisma.io"
    password: "IlikeTurtles"
  }) {
    id
    name
    email
    password
  }
}

create新vote:


const newVote = await prisma
  .createVote({
    user: {
      connect: {
        email: "alice@prisma.io"
      }
    },
    link: {
      connect: {
        id: "cjli47wr3005b0a23m9crhh0e"
      }
    }
  })

# generated mutation
mutation {
  createVote(data: {
    user: {
      connect: {
        email: "alice@prisma.io"
      }
    }
    link: {
      connect: {
        id: "cjli47wr3005b0a23m9crhh0e"
      }
    }
  }) {
    id
  }
}

create新用户并加两个新links:


const newUserWithLinks = await prisma
  .createUser({
    name: "Alice",
    email: "alice@prisma.io",
    password: "IlikeTurtles",
    links: {
      create: [{
        description: "My first link",
        url: "https://www.prisma.io"
      }, {
        description: "My second link",
        url: "https://www.howtographql.com"
      }]
    }, 
  })

# generated mutation
mutation {
  createUser(data: {
    name: "Alice"
    email: "alice@prisma.io"
    password: "IlikeTurtles"
    links: {
      create: [{
        description: "My first link",
        url: "https://www.prisma.io"
      }, {
        description: "My second link",
        url: "https://www.howtographql.com"
      }]
    }
  }) {
    id
    name
    email
    password
  }
}

当在数据库中更新现有记录中,update-方法接收具有两个字段的一个输入对象:

  • data:这类似于你提供给一个create-方法输入对象。它包含模型更新的字段,让你提供的关系数据通过嵌套对象写入
  • where:这是用来选择要更新的记录。你可以使用任何[唯一]字段来标识记录。

查看data的类型和where用于LinkUserVote

  • data

    • 查看updateLinkdata字段的类型这里
    • 查看updateUserdata字段的类型这里
    • 查看updateVotedata字段的类型这里
  • where

    • 查看updateLinkwhere字段的类型这里
    • 查看updateUserwhere字段的类型这里
    • 查看updateVotewhere字段的类型这里

每个方法调用返回一个包含刚更新了模型的所有字段的对象。

设置现有用户一个新的名字:


const updatedUser = await prisma
  .updateUser({
    data: {
      name: "Alice"
    },
    where: {
      id: "cjli512bd005g0a233s1ogbgy"
    }
  })

# generated mutation
mutation {
  updateUser(
    data: {
      name: "Alice"
    }
    where: {
      id: "cjli512bd005g0a233s1ogbgy"
    }
  ) {
    id
    name
    email
    password
  }
}

Update一个链接,改变它的发布者为不同的用户:


const updatedLink = await prisma
  .updateLink({
    data: {
      postedBy: {
        connect: {
          id: "cjli512bd005g0a233s1ogbgy"
        }
      },
    },
    where: {
      id: "cjli47wr3005b0a23m9crhh0e"
    }
  })

mutation {
  updateLink(
    data: {
      postedBy: {
        connect: {
          id: "cjli512bd005g0a233s1ogbgy"
        }
      }
    }
    where: {
      id: "cjli47wr3005b0a23m9crhh0e"
    }
  ) {
    id
    createdAt
    description
    url
  }
}

delete发布vote的用户:


const updatedVote = await prisma
  .updateVote({
    data: {
      user: {
        delete: true
      },
    },
    where: {
      id: "cjli5aual005n0a233ekv89o4"
    }
  })

mutation {
  updateVote(
    data: {
      user: {
        delete: true
      }
    }
    where: {
      id: "cjli5aual005n0a233ekv89o4"
    }
  ) {
    id
  }
}

为了成功执行此操作,vote的user不能是必填字段。否则,每一个Vote需要连接到一个User,删除就报错了。

当从数据库中删除记录,该delete-方法接收一个输入对象,指定哪个记录是要被删除。类型此输入对象的是相同的update-方法where对象。

该对象的属性对应于被标记为唯一的模型的那些字段。对于上面的示例数据模型,这意味着,对于UserVoteLink它有一个id属性。对于User它另外接受email字段。

查看类型的输入对象的LinkUserVote

每个方法调用返回一个包含刚删除的模型的所有字段的对象。

delete其ID链接:


const deletedLink = await prisma
  .deleteLink({
    id: "cjli47wr3005b0a23m9crhh0e"
  })

mutation {
  deleteLink(where: {
    id: "cjli47wr3005b0a23m9crhh0e"
  }) {
    id
    createdAt
    description
    url
  }
}

通过他们的email来delete用户:


const deletedUser = await prisma
  .deleteUser({
    email: "alice@prisma.io"
  })

mutation {
  deleteUser(where: {
    email: "alice@prisma.io"
  }) {
    id
    createdAt
    description
    url
  }
}

UPSERT操作允许你尝试更新现有的记录。如果该记录实际上还不存在,它将被创建。该upsert的方法是create-和update-的搭配方法,这意味着他们收到有三个字段输入参数:

  • where:相同于在update方法中提供的where字段
  • update:相同于在update的方法中提供的data字段
  • create:相同于在create的方法中提供的输入input

Update链接的URL。如果该链接不存在,创建一个新的:


const updatedOrCreatedLink = await prisma
  .upsertLink({
    where: {
      id: "cjli47wr3005b0a23m9crhh0e"
    },
    update: {
      url: "https://www.howtographql.com"
    },
    create: {
      url: "https://www.howtographql.com",
      description: "Fullstack GraphQL Tutorial"
    }
  })

mutation {
  upsertLink(
    where: {
      id: "cjli47wr3005b0a23m9crhh0e"
    }
    update: {
      url: "https://www.howtographql.com"
    }
    create: {
      url: "https://www.howtographql.com"
      description: "Fullstack GraphQL Tutorial"
    }
  ) {
    id
  }
}

该Prisma的clientAPI提供了特殊的方法来更新或一次删除多条记录。GraphQL API中的相应的Mutation被称为[批量Mutation(#批量Mutation)。每个updateMany-和deleteMany-方法返回最终受到影响的操作记录数。

Update三个links,通过其ID指定,将其网址重置为空string:


const updatedLinksCount = await prisma
  .updateManyLinks({
    where: {
      id_in: ["cjli6tknz005s0a23uf0lmlve", "cjli6tnkj005x0a2325ynfpb9", "cjli6tq3200620a23s4lp8npd"]
    },
    data: {
      url: ""
    },
  }).count

mutation {
  updateManyLinks({
    where: {
      id_in: ["cjli6tknz005s0a23uf0lmlve", "cjli6tnkj005x0a2325ynfpb9", "cjli6tq3200620a23s4lp8npd"]
    }
    data: {
      url: ""
    }
  }) {
    count
  }
}

注意

如果一个或多个所提供的ID没有在数据库中实际存在,操作将 不返回错误。

Update 所有links的描述中包含字符串'graphql`的数据,其网址重置为空string:


const updatedLinksCount = await prisma
  .updateManyLinks({
    where: {
      description_contains: "graphql"
    },
    data: {
      url: ""
    },
  }).count

mutation {
  updateManyLinks({
    where: {
      description_contains: "graphql"
    }
    data: {
      url: ""
    }
  }) {
    count
  }
}

delete在2018年之前创建的所有链接:


const deleteLinksCount = await prisma
  .deleteManyLinks({
    createdAt_lte: "2018"
  }).count

mutation {
  deleteManyLinks(where: {
    createdAt_lte: "2018"
  }) {
    count
  }
}

嵌套的对象写入操作让你在一个单一的Mutation中修改多个模型数据库记录。Prisma的GraphQL API相应的概念被称为嵌套Mutation。嵌套对象写入可供create-和update的方法。

如果模型具有相对于不同的schema,对应关系字段被设定为具有以下性质中的一个子集的对象:

  • create:创建相关模型的新纪录,并通过关系将其连接。
  • update:更新通过关系已经连接了相关模型的现有记录。
  • upsert:更新相关模型的现有记录或创建并连接一个新的。
  • delete:删除通过关系连接的相关模型的现有记录。
  • connect:通过连接关系的相关模型的现有记录。
  • disconnect:删除通过关系连接相关模型的现有记录。

create新用户和两个新的link,并连接一个现有的link:


const newUserWithLinks = await prisma
  .createUser({
    name: "Alice",
    email: "alice@prisma.io",
    password: "IlikeTurtles",
    links: {
      create: [{
        description: "My first link",
        url: "https://www.prisma.io"
      }, {
        description: "My second link",
        url: "https://www.howtographql.com"
      }],
      connect: {
        id: "cjli6tknz005s0a23uf0lmlve"
      }
    }, 
  })

# generated mutation
mutation {
  createUser(data: {
    name: "Alice"
    email: "alice@prisma.io"
    password: "IlikeTurtles"
    links: {
      create: [{
        description: "My first link",
        url: "https://www.prisma.io"
      }, {
        description: "My second link",
        url: "https://www.howtographql.com"
      }]
      connect: {
        id: "cjli6tknz005s0a23uf0lmlve"
      }
    }
  }) {
    id
    name
    email
    password
  }
}

delete用户的链接:


const updatedUser = await prisma
  .updateUser({
    where: {
      id: "cjli8znnd006n0a23ywc6wf8w"
    },
    data: {
      links: {
        delete: {
          id: "cjli6tknz005s0a23uf0lmlve"
        }
      }
    }
  })

mutation {
  updateUser(
    where: {
      id: "cjli8znnd006n0a23ywc6wf8w"
    }
    data: {
      links: {
        delete: {
          id: "cjli6tknz005s0a23uf0lmlve"
        }
      }
    }
  ) {
    id
  }
}

该Prisma的client,使用\$subscribe属性实时更新和订阅数据库事件和数据。对于你的数据模型中的每个模型类型,Prisma client公开以此属性的模型命名的(小写)一个函数:Subscriptions。使用此函数意味着比对该模型的[写入]事件(即createupdatedelete)有实时需求。你可以提供一个过滤器对象,使得可以进一步约束要接收更新的事件类型。该函数返回async iterator,只要发生指定的数据库事件,就会发出事件通知。

\$subscribe API是基于[WebSockets的(https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)。

Subscribe"新建"和"更新"User的事件:


const createdAndUpdatedUserIterator = await prisma.$subscribe.user({
  mutation_in: ['CREATED', 'UPDATED']
}).node()

_SubscribeUser的电子邮件地址有包含字符串'gmail`的更新:


const userIterator = await prisma.$subscribe.user({
  email_contains: `gmail` 
}).node()

该Prisma的client,你可以为你在使用$exists属性中的数据库中是否存在一定的记录。对于你的[数据模型]每个模型类型,Prisma client公开此属性的模型命名的(小写)一个函数。这些函数的接收过滤对象作为指定该记录的条件,并返回一个布尔值;如果有至少一个数据库记录符合指定过滤,该值是TRUE,否则返回FALSE。

输入对象具有用于[过滤列表]相同的类型。

检查是否有具有特定ID 存在的用户:


const userExists = prisma.$exists.user({
  id: "cjli6tko8005t0a23fid7kke7"
})

检查是否有用户名为AliceBob 的user存在:


const userExists = prisma.$exists.user({
  name_in: ['Alice', 'Bob']
})

检查是否有在描述中有prismagraphql字段存在的link,并且创建于2018年:


const linkExists = await prisma.$exists.link({
  AND: [
    {
      OR: [{
        description_contains: "graphql",
      }, {
        description_contains: "prisma",
      }]
    },
    {
      AND: [{
        createdAt_gt: "2017"
      }, {
        createdAt_lt: "2019"
      }]
    }
  ],
})

该Prisma的client,可以直接发送GraphQL Query和Mutation,$request方法请求你的Prisma service:


$request: <T = any>(query: string, variables?: {[key: string]: any}) => Promise<T>;

查询单个用户:


  query {
    user(id: "cjcdi63j80adw0146z7r59bn5") {
      id
      name
    }
  }
prisma.request(query)
  .then(result => console.log(result))
// 示例result:
// {"data": { "user": { "id": "cjcdi63j80adw0146z7r59bn5", "name": "Sarah" } } }

使用variables查询单个用户:


  query ($userId: ID!){
    user(id: $userId) {
      id
      name
    }
  }
const variables = { userId: 'cjcdi63j80adw0146z7r59bn5' }
prisma.request(query, variables)
  .then(result => console.log(result))
// 示例result:
// {"data": { "user": { "id": "cjcdi63j80adw0146z7r59bn5", "name": "Sarah" } } }

Prisma client基于Prisma API的GraphQL schema定义生成操作。对于reading数据,它基本上复制你Prisma service中的GraphQL Query

对于此页面,我们假设你的Prisma API基于以下datamodel:


type Link {
  id: ID! @unique
  createdAt: DateTime!
  description: String!
  url: String!
  postedBy: User
  votes: [Vote!]!
}
type User {
  id: ID! @unique
  name: String!
  email: String! @unique
  password: String!
  links: [Link!]!
  votes: [Vote!]!
}
type Vote {
  id: ID! @unique
  link: Link!
  user: User!
}
  • 你可以查看API生成的GraphQL schema这里
  • 你可以查看生成的TypeScript client此处

每当使用Prisma client查询模型时,都会获取该模型的所有字段。无论是查询单个对象还是对象列表,都是如此。

例如,以下查询返回单个"User"的所有标量字段:


const user: UserNode = await prisma.user({ email: "bob@prisma.io" })

在这种情况下,返回的user对象将具有四个属性(对应于User模型的标量字段):idnameemailpassword

linksvotes字段都是relation fields,因此不包含在查询中。

以下是获取User对象list的示例:


const users: UserNode[] = await prisma.users()

与前面的查询类似,users数组中的每个对象只有标量和无关系字段。

对于datamodel中的每个模型类型,在Prisma clientAPI中生成一种方法,允许获取该模型的单个对象。该方法以类型命名,但以小写字符开头。对于上面的示例数据模型,获取单个"User","Link"和"Vote"对象的三种方法称为"user","link"和"vote"。

这些函数的输入是一个对象,它具有模型的任何[唯一]字段作为属性。这意味着,对于所有三种方法,都接受id字段(因为相应的模型每个都有一个注释为@uniqueid字段)。 user方法的输入对象另外有一个email字段。

查看LinkUserVote的输入对象的类型

  • 查看Link的"where"类型here
  • 查看User的"where"类型here
  • 查看Vote的"where"类型here

通过其id获取单个投票:


const vote:VoteNode = await prisma.vote({id:"cjlgpyueg001o0a239d3i07ao"})

# generated query
query {
  vote(where: {
    id: "cjlgpyueg001o0a239d3i07ao"
  }) {
    id
  }
}

通过email获取单个用户:


const用户:UserNode = await prisma.user({email:"alice@prisma.io"})

# generated query
query {
  user(where: {
    email: "alice@prisma.io"
  }) {
    id
  }
}

对于datamodel中的每个模型类型,在Prisma client API中生成一个方法,允许获取这些模型对象的列表。该方法以模型命名,但以小写字符开头并使用复数形式。对于上面的示例数据模型,获取"User","Link"和"Vote"模型列表的三种方法称为"users","links"和"votes"。

这些函数的输入参数是一个具有以下属性的对象:

查询 all links:


const links: LinkNode[] = await prisma.links()

# generated query
query {
  links {
    id
    createdAt
    url
    description
  }
}

获取users列表:


const users: UserNode[] = await prisma.users()

# generated query
query {
  users {
    id
    name
    email
    password
  }
}

Prisma client基于fluent API来查询数据图中的关系。这意味着你可以简单地链式调用你的方法来返回模型的关系属性。

注意

这仅在检索单个对象时才有可能,而不是用于列表。这意味着你无法查询列表中返回的对象的关系字段,例如:


//不可能
const result = await prisma
  .users()
  .links()

在这个例子中,users()已经返回一个列表,因此不可能查询列表中每个用户对象的links关系。

Query查询单个user的所有链接:


const linksByUser: LinkNode[] = await prisma
  .user({ email: "alice@prisma.io" })
  .links()

query {
  user(where: {
    email: "alice@prisma.io"
  }) {
    links {
      id
      createdAt
      description
      url
    }
  }
}

 查询某个user所做的所有投票:


const votesByUser: VoteNode[] = await prisma
  .user({ email: "alice@prisma.io" })
  .votes()

query {
  user(where: {
    email: "alice@prisma.io"
  }) {
    votes {
      id
    }
  }
}

你可以使用$fragment API功能(基于GraphQL)指定要检索的字段,而不是查询模型的所有标量字段(这是默认行为)。这对于排除大量不需要的字段(如BLOB值或大字符串)或检索关系很有用。

获取用户的nameemail以及相关linksdescriptionurl:


const fragment = `
fragment UserWithLinks on User {
  name
  email
  links {
    description
    url
  }
}
`
const userWithPosts = await prisma.users().$fragment(fragment)

query {
  users {
    ...UserWithLinks
  }
}
fragment UserWithLinks on User {
  name
  email
  links {
    description
    url
  }
}

Basic过滤器允许你指定某些条件来约束应在列表中返回哪些对象。过滤器在输入参数的where对象中指定,任何列表查询都接受该对象。

where对象的类型取决于生成它的模型。

查看LinkUserVotewhere类型

  • 查看Link的"where"类型here
  • 查看User的"where"类型here
  • 查看Vote的"where"类型here

也可以使用ANDOR字段组合多个过滤器。

找到名称中包含"A"的用户:


const usersWithAInName: UserNode[] = await prisma
  .users({
    where: {
      name_contains: "A"
    }
  })

query {
  users(where: {
      name_contains: "A"
  }) {
    id
    name
    email
    password
  }
}

使用自动完成功能来探索过滤系统

查询称为"Alice"或"Bob`的用户:


const usersCalledAliceOrBob: UserNode[] = await prisma
  .users({
    where: {
      name_in: ["Alice", "Bob"]
    }
  })

query {
  users(where: {
    name_in: ["Alice", "Bob"]
  }) {
    id
    name
    email
    password
  }
}

获取2018年12月24日之前创建的链接:


const linksBeforeChristmas: LinkNode[] = await prisma
  .links({
    where: {
      createdAt_lt: "2018-12-24" 
    }
  })

query {
  links(where: {
    createdAt_lt: "2018-12-24" 
  }) {
    id
    createdAt
    description
    url
  }
}

Prisma clientAPI中的日期和时间遵循ISO 8601标准,该标准通常具有以下形式:YYYY-MM-DDThh:mm:ss

查询在description中有prisma graphql的链接并且是在2018年创建的:


const filteredLinks: LinkNode[] = await prisma
  .links({
    where: {
      AND: [
        {
          OR: [{
            description_contains: "graphql",
          }, {
            description_contains: "prisma",
          }]
        }, 
        {
          AND: [{
            createdAt_gt: "2017"
          }, {
            createdAt_lt: "2019"
          }]
        }
      ],
    }
  })

query {
  links(where: {
    OR: [{
      description_contains: "graphql",
    }, {
      description_contains: "prisma",
    }]
    AND: [{ 
      createdAt_lt: "2019"
    }, { 
      createdAt_gt: "2017" 
    }]
  }) {
    id
    description
  }
}

实际上可以省略AND过滤器,因为默认情况下使用logical and组合了多个过滤条件。这意味着上面的过滤器也可以表示如下:


const filteredLinks: LinkNode[] = await prisma
  .links({
    where: {
      OR: [{
        description_contains: "graphql"
      }, {
        description_contains: "prisma"
      }],
      createdAt_gt: "2017",
      createdAt_lt: "2019"
    }
  })

query {
  links(where: {
    OR: [{
      description_contains: "graphql",
    }, {
      description_contains: "prisma",
    }],
    createdAt_lt: "2019",
    createdAt_gt: "2017" 
  }) {
    id
    createdAt
    description
    url
  }
}

关系过滤器可用于约束关系列表字段上的返回对象。用于过滤的类型与基本过滤器相同,唯一的区别是过滤器不应用于方法调用的第一级,而是在第二级查询关系时。


const linksByUserBeforeChristmas: LinkNode[] = await prisma
  .user({ email: "alice@prisma.io" })
  .links({
    where: {
      createdAt_lt: "2017-12-24" 
    }
  })

query {
 user(where: {
  email: "alice@prisma.io"
 }) {
    links(where: {
      createdAt_lt: "2017-12-24" 
    }) {
      id
      createdAt
      description
      url
  }
 }
}

查询模型对象列表时,可以按该模型类型的任何标量字段对列表进行排序。因此,每个生成的查询模型列表的方法都接受其输入对象上的orderBy字段。

orderBy字段的类型取决于生成它的模型的标量字段。

查看linkuser和'vote'的orderBy类型

  • 查看linkorderBy类型here
  • 查看userorderBy类型here
  • 查看VoteorderBy类型here

_按创建日期(升序)_links:


const sortedLinks: LinkNode[] = prisma
  .links({
    orderBy: "createdAt_ASC"
  })

query {
  links(orderBy: createdAt_ASC) {
    id
    createdAt
    description
    url
  }
}

按字母顺序排序用户名(降序):


const sortedUsers: UserNode[] = prisma
  .users({
    orderBy: "name_DESC"
  })

query {
  users(orderBy: name_DESC) {
    id
    name
    email
    password
  }
}

查询模型对象列表时,可以通过提供分页参数来获取该列表的部分信息。常在feed流中使用。

你可以在对象中向前或从后往前并提供可选的起始对象:

  • 从前往后,使用first;用after指定一个起始对象。
  • 从后往前,请使用last;用before指定一个起始对象。

不能firstbeforelastafter结合起来。如果你在查询中这样做,before/after将被忽略,实际上只应用firstlast(在列表的开头或结尾,取决于你使用的是哪个) 。

请注意,你可以在没有错误消息的情况下查询比实际存在的对象更多的对象。

你还可以通过提供skip参数跳过任意方向的任意数量的对象:

  • 当使用first时,skip会跳过列表开头的对象。
  • 当使用last时,skip跳过列表末尾的对象。

对于以下示例,我们假设一个正好包含30个对象的列表:

查询前3个链接(从前往后):


const links: LinkNode[] = await prisma
  .links({
    first: 3
  })

query {
  links(first: 3) {
    id
    createdAt
    description
    url
  }
}

查询从位置6到位置10的对象(从前往后):


const links: LinkNode[] = await prisma
  .links({
    first: 5, 
    skip: 5
  })

query {
  links(
    first: 5 
    skip: 5
  ) {
    id
    createdAt
    description
    url
  }
}

查询最后3个对象(从后往前):


const links: LinkNode[] = await prisma
  .links({
    last: 3
  })

query {
  links(last: 3) {
    id
    createdAt
    description
    url
  }
}

查询从第21位到第27位的对象(从后往前):


const links: LinkNode[] = await prisma
  .links({
    last: 7,
    skip: 3
  })

query {
  links(
    last: 7
    skip: 3
  ) {
    id
    createdAt
    description
    url
  }
}

使用cixnen24p33lo0143bexvr52n作为id查询对象之后的前3个对象:


const links: LinkNode[] = await prisma
  .links({
    first: 3,
    after: "cixnen24p33lo0143bexvr52n"
  })

query {
  links(
    first: 3
    after: "cixnen24p33lo0143bexvr52n"
  ) {
    id
    createdAt
    description
    url
  }
}

使用cixnen24p33lo0143bexvr52n作为id跳过3条数据查询后面的5个对象:


const links: LinkNode[] = await prisma
  .links({
    first: 5,
    after: "cixnen24p33lo0143bexvr52n",
    skip: 3
  })

query {
  links(
    first: 5
    after: "cixnen24p33lo0143bexvr52n"
    skip: 3
  ) {
    id
    createdAt
    description
    url
  }
}

使用cixnen24p33lo0143bexvr52n作为id查询对象之前的最后5个对象:


const links: LinkNode[] = await prisma
  .links({
    last: 5,
    before: "cixnen24p33lo0143bexvr52n"
  })

query {
  links(
    last: 5
    before: "cixnen24p33lo0143bexvr52n"
  ) {
    id
    createdAt
    description
    url
  }
}

查询节点之前的最后3个节点,其中cixnen24p33lo0143bexvr52n为id并跳过5个:


const links: LinkNode[] = await prisma
  .links({
    last: 3,
    before: "cixnen24p33lo0143bexvr52n",
    skip: 5
  })

query {
  links(
    last: 3 
    before: "cixnen24p33lo0143bexvr52n"
    skip: 5
  ) {
    id
    createdAt
    description
    url
  }
}

你可以通过[Connection查询]提交聚合查询。支持以下聚合功能:

  • count:计算列表中的对象数
  • avg(即将推出):计算数字列表的平均值。
  • median(即将推出):计算数字列表的中位数。
  • max(即将推出):返回数字列表中最大的元素。
  • min(即将推出):返回数字列表中的最小元素。
  • sum(即将推出):计算数字列表的总和。

请参阅thisGitHub问题以了解有关即将推出的聚合功能的更多信息。

Count链接对象的数量:


const linkCount: number = await prisma
  .linksConnection()
  .aggregate()
  .count()

query {
  linksConnection {
    aggregate {
      count
    }
  }
}

对于前面创建的的数据模型,每个模型类型生成了写入数据六种方法。这些在GraphQL schema,例如用于User模型中的Mutation而得到:

  • createUser:创建一个新的User记录在数据库中

  • updateUser:更新现有User记录在数据库中

  • deleteUser:从数据库中删除现有的User记录

  • upsertUser:更新现有的或在数据库中创建一个新的User纪录

  • updateManyUsers:更新许多现有的User数据库中的记录

  • deleteManyUsers:从数据库中删除现有的许多User记录

  • 你可以查看一下生成GraphQL schema的API 这里

  • 你可以查看要生成的JavaScript client这里

这些方法中的一个的每个调用被作为[事务]执行,这意味着它要么保证完全成功,或者如果它只是部分地失败但要被全部取消而回到原先状态,所以不必担心数据一致性。

当在数据库中创建新的记录,create方法需要用一个输入对象包裹起来所有数据。它还提供了一种用于模型创建关系数据,这可以通过使用嵌套对象写入来提供。

每个方法调用的返回包含刚刚创建的模型的所有字段。

create新用户:


const newUser: UserNode = await prisma
  .createUser({
    name: "Alice",
    email: "alice@prisma.io",
    password: "IlikeTurtles"
  })

# generated mutation
mutation {
  createUser(data: {
    name: "Alice"
    email: "alice@prisma.io"
    password: "IlikeTurtles"
  }) {
    id
    name
    email
    password
  }
}

create新vote:


const newVote: VoteNode = await prisma
  .createVote({
    user: {
      connect: {
        email: "alice@prisma.io"
      }
    },
    link: {
      connect: {
        id: "cjli47wr3005b0a23m9crhh0e"
      }
    }
  })

# generated mutation
mutation {
  createVote(data: {
    user: {
      connect: {
        email: "alice@prisma.io"
      }
    }
    link: {
      connect: {
        id: "cjli47wr3005b0a23m9crhh0e"
      }
    }
  }) {
    id
  }
}

create新用户并加两个新links:


const newUserWithLinks: UserNode = await prisma
  .createUser({
    name: "Alice",
    email: "alice@prisma.io",
    password: "IlikeTurtles",
    links: {
      create: [{
        description: "My first link",
        url: "https://www.prisma.io"
      }, {
        description: "My second link",
        url: "https://www.howtographql.com"
      }]
    }, 
  })

# generated mutation
mutation {
  createUser(data: {
    name: "Alice"
    email: "alice@prisma.io"
    password: "IlikeTurtles"
    links: {
      create: [{
        description: "My first link",
        url: "https://www.prisma.io"
      }, {
        description: "My second link",
        url: "https://www.howtographql.com"
      }]
    }
  }) {
    id
    name
    email
    password
  }
}

当在数据库中更新现有记录中,update-方法接收具有两个字段的一个输入对象:

  • data:这类似于你提供给一个create-方法输入对象。它包含模型更新的字段,让你提供的关系数据通过嵌套对象写入
  • where:这是用来选择要更新的记录。你可以使用任何[唯一]字段来标识记录。

查看data的类型和where用于LinkUserVote

  • data

    • 查看updateLinkdata字段的类型这里
    • 查看updateUserdata字段的类型这里
    • 查看updateVotedata字段的类型这里
  • where

    • 查看updateLinkwhere字段的类型这里
    • 查看updateUserwhere字段的类型这里
    • 查看updateVotewhere字段的类型这里

每个方法调用返回一个包含刚更新了模型的所有字段的对象。

设置现有用户一个新的名字:


const updatedUser: UserNode = await prisma
  .updateUser({
    data: {
      name: "Alice"
    },
    where: {
      id: "cjli512bd005g0a233s1ogbgy"
    }
  })

# generated mutation
mutation {
  updateUser(
    data: {
      name: "Alice"
    }
    where: {
      id: "cjli512bd005g0a233s1ogbgy"
    }
  ) {
    id
    name
    email
    password
  }
}

Update一个链接,改变它的发布者为不同的用户:


const updatedLink: LinkNode = await prisma
  .updateLink({
    data: {
      postedBy: {
        connect: {
          id: "cjli512bd005g0a233s1ogbgy"
        }
      },
    },
    where: {
      id: "cjli47wr3005b0a23m9crhh0e"
    }
  })

mutation {
  updateLink(
    data: {
      postedBy: {
        connect: {
          id: "cjli512bd005g0a233s1ogbgy"
        }
      }
    }
    where: {
      id: "cjli47wr3005b0a23m9crhh0e"
    }
  ) {
    id
    createdAt
    description
    url
  }
}

delete发布vote的用户:


const updatedVote: VoteNode = await prisma
  .updateVote({
    data: {
      user: {
        delete: true
      },
    },
    where: {
      id: "cjli5aual005n0a233ekv89o4"
    }
  })

mutation {
  updateVote(
    data: {
      user: {
        delete: true
      }
    }
    where: {
      id: "cjli5aual005n0a233ekv89o4"
    }
  ) {
    id
  }
}

为了成功执行此操作,vote的user不能是必填字段。否则,每一个Vote需要连接到一个User,删除就报错了。

当从数据库中删除记录,该delete-方法接收一个输入对象,指定哪个记录是要被删除。类型此输入对象的是相同的update-方法where对象。

该对象的属性对应于被标记为唯一的模型的那些字段。对于上面的示例数据模型,这意味着,对于UserVoteLink它有一个id属性。对于User它另外接受email字段。

查看类型的输入对象的LinkUserVote

每个方法调用返回一个包含刚删除的模型的所有字段的对象。

delete其ID链接:


const deletedLink: LinkNode = await prisma
  .deleteLink({
    id: "cjli47wr3005b0a23m9crhh0e"
  })

mutation {
  deleteLink(where: {
    id: "cjli47wr3005b0a23m9crhh0e"
  }) {
    id
    createdAt
    description
    url
  }
}

通过他们的email来delete用户:


const deletedUser: UserNode = await prisma
  .deleteUser({
    email: "alice@prisma.io"
  })

mutation {
  deleteUser(where: {
    email: "alice@prisma.io"
  }) {
    id
    createdAt
    description
    url
  }
}

UPSERT操作允许你尝试更新现有的记录。如果该记录实际上还不存在,它将被创建。该upsert的方法是create-和update-的搭配方法,这意味着他们收到有三个字段输入参数:

  • where:相同于在update方法中提供的where字段
  • update:相同于在update的方法中提供的data字段
  • create:相同于在create的方法中提供的输入input

Update链接的URL。如果该链接不存在,创建一个新的:


const updatedOrCreatedLink: LinkNode = await prisma
  .upsertLink({
    where: {
      id: "cjli47wr3005b0a23m9crhh0e"
    },
    update: {
      url: "https://www.howtographql.com"
    },
    create: {
      url: "https://www.howtographql.com",
      description: "Fullstack GraphQL Tutorial"
    }
  })

mutation {
  upsertLink(
    where: {
      id: "cjli47wr3005b0a23m9crhh0e"
    }
    update: {
      url: "https://www.howtographql.com"
    }
    create: {
      url: "https://www.howtographql.com"
      description: "Fullstack GraphQL Tutorial"
    }
  ) {
    id
  }
}

该Prisma的clientAPI提供了特殊的方法来更新或一次删除多条记录。GraphQL API中的相应的Mutation被称为[批量Mutation(#批量Mutation)。每个updateMany-和deleteMany-方法返回最终受到影响的操作记录数。

Update三个links,通过其ID指定,将其网址重置为空string:


const updatedLinksCount: number = await prisma
  .updateManyLinks({
    where: {
      id_in: ["cjli6tknz005s0a23uf0lmlve", "cjli6tnkj005x0a2325ynfpb9", "cjli6tq3200620a23s4lp8npd"]
    },
    data: {
      url: ""
    },
  }).count

mutation {
  updateManyLinks({
    where: {
      id_in: ["cjli6tknz005s0a23uf0lmlve", "cjli6tnkj005x0a2325ynfpb9", "cjli6tq3200620a23s4lp8npd"]
    }
    data: {
      url: ""
    }
  }) {
    count
  }
}

注意

如果一个或多个所提供的ID没有在数据库中实际存在,操作将 不返回错误。

Update 所有links的描述中包含字符串'graphql`的数据,其网址重置为空string:


const updatedLinksCount: number = await prisma
  .updateManyLinks({
    where: {
      description_contains: "graphql"
    },
    data: {
      url: ""
    },
  }).count

mutation {
  updateManyLinks({
    where: {
      description_contains: "graphql"
    }
    data: {
      url: ""
    }
  }) {
    count
  }
}

delete在2018年之前创建的所有链接:


const deleteLinksCount: number = await prisma
  .deleteManyLinks({
    createdAt_lte: "2018"
  }).count

mutation {
  deleteManyLinks(where: {
    createdAt_lte: "2018"
  }) {
    count
  }
}

嵌套的对象写入操作让你在一个单一的Mutation中修改多个模型数据库记录。Prisma的GraphQL API相应的概念被称为嵌套Mutation。嵌套对象写入可供create-和update的方法。

如果模型具有相对于不同的schema,对应关系字段被设定为具有以下性质中的一个子集的对象:

  • create:创建相关模型的新纪录,并通过关系将其连接。
  • update:更新通过关系已经连接了相关模型的现有记录。
  • upsert:更新相关模型的现有记录或创建并连接一个新的。
  • delete:删除通过关系连接的相关模型的现有记录。
  • connect:通过连接关系的相关模型的现有记录。
  • disconnect:删除通过关系连接相关模型的现有记录。

create新用户和两个新的link,并连接一个现有的link:


const newUserWithLinks: UserNode = await prisma
  .createUser({
    name: "Alice",
    email: "alice@prisma.io",
    password: "IlikeTurtles",
    links: {
      create: [{
        description: "My first link",
        url: "https://www.prisma.io"
      }, {
        description: "My second link",
        url: "https://www.howtographql.com"
      }],
      connect: {
        id: "cjli6tknz005s0a23uf0lmlve"
      }
    }, 
  })

# generated mutation
mutation {
  createUser(data: {
    name: "Alice"
    email: "alice@prisma.io"
    password: "IlikeTurtles"
    links: {
      create: [{
        description: "My first link",
        url: "https://www.prisma.io"
      }, {
        description: "My second link",
        url: "https://www.howtographql.com"
      }]
      connect: {
        id: "cjli6tknz005s0a23uf0lmlve"
      }
    }
  }) {
    id
    name
    email
    password
  }
}

delete用户的链接:


const updatedUser: UserNode = await prisma
  .updateUser({
    where: {
      id: "cjli8znnd006n0a23ywc6wf8w"
    },
    data: {
      links: {
        delete: {
          id: "cjli6tknz005s0a23uf0lmlve"
        }
      }
    }
  })

mutation {
  updateUser(
    where: {
      id: "cjli8znnd006n0a23ywc6wf8w"
    }
    data: {
      links: {
        delete: {
          id: "cjli6tknz005s0a23uf0lmlve"
        }
      }
    }
  ) {
    id
  }
}

该Prisma的client,使用\$subscribe属性实时更新和订阅数据库事件和数据。对于你的数据模型中的每个模型类型,Prisma client公开以此属性的模型命名的(小写)一个函数:Subscriptions。使用此函数意味着比对该模型的[写入]事件(即createupdatedelete)有实时需求。你可以提供一个过滤器对象,使得可以进一步约束要接收更新的事件类型。该函数返回async iterator,只要发生指定的数据库事件,就会发出事件通知。

\$subscribe API是基于[WebSockets的(https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)。

Subscribe"新建"和"更新"User的事件:


const createdAndUpdatedUserIterator: UserAsyncIterator = await db.$subscribe.user({
  mutation_in: ['CREATED', 'UPDATED']
}).node()

_SubscribeUser的电子邮件地址有包含字符串'gmail`的更新:


const userIterator: UserAsyncIterator = await db.$subscribe.user({
  email_contains: `gmail` 
}).node()

该Prisma的client,你可以为你在使用$exists属性中的数据库中是否存在一定的记录。对于你的[数据模型]每个模型类型,Prisma client公开此属性的模型命名的(小写)一个函数。这些函数的接收过滤对象作为指定该记录的条件,并返回一个布尔值;如果有至少一个数据库记录符合指定过滤,该值是TRUE,否则返回FALSE。

输入对象具有用于[过滤列表]相同的类型。

检查是否有具有特定ID 存在的用户:


const userExists: boolean = prisma.$exists.user({
  id: "cjli6tko8005t0a23fid7kke7"
})

检查是否有用户名为AliceBob 的user存在:


const userExists: boolean = prisma.$exists.user({
  name_in: ['Alice', 'Bob']
})

检查是否有在描述中有prismagraphql字段存在的link,并且创建于2018年:


const linkExists: boolean = await prisma.$exists.link({
  AND: [
    {
      OR: [{
        description_contains: "graphql",
      }, {
        description_contains: "prisma",
      }]
    },
    {
      AND: [{
        createdAt_gt: "2017"
      }, {
        createdAt_lt: "2019"
      }]
    }
  ],
})

该Prisma的client,可以直接发送GraphQL Query和Mutation,$request方法请求你的Prisma service:


$request: <T = any>(query: string, variables?: {[key: string]: any}) => Promise<T>;

查询单个用户:


  query {
    user(id: "cjcdi63j80adw0146z7r59bn5") {
      id
      name
    }
  }
const result: any = prisma.$request(query)
// 示例result:
// {"data": { "user": { "id": "cjcdi63j80adw0146z7r59bn5", "name": "Sarah" } } }

使用variables查询单个用户:


  query ($userId: ID!){
    user(id: $userId) {
      id
      name
    }
  }
const variables: UserWhereUniqueInput = { id: 'cjcdi63j80adw0146z7r59bn5' }
const result: any = prisma.$request(query, variables)
  .then(result => console.log(result))
// 示例result:
// {"data": { "user": { "id": "cjcdi63j80adw0146z7r59bn5", "name": "Sarah" } } }

每当使用Prisma client查询模型时,都会获取该模型的all标量fields。 无论是查询单个对象还是对象列表,都是如此。

例如,以下查询返回单个"User"的所有标量字段:


user := client.User(&prisma.UserWhereInput{ "email": "bob@prisma.io" })

在这种情况下,返回的user对象将具有四个属性(对应于User模型的标量字段):idnameemailpassword

linksvotes字段都是relation fields,因此不包含在查询中。

以下是获取User对象list的示例:


users := client.Users(nil).Exec()

与前面的查询类似,users数组中的每个对象只有标量和无关系字段。

与JS和TS类似,仅语法不同。

当在数据库中创建新的记录,create法需要它包装上创建的所有记录的字段一个输入对象。它还提供了一种用于模型创建关系数据,这可以通过使用嵌套对象写入来供给。

每个方法调用返回包含刚刚创建的模型的所有字段的对象。

create新用户:


name := "Alice",
email := "alice@prisma.io",
password := "IlikeTurtles"
newUser, err := db.CreateUser(&prisma.UserCreateInput{
  Name: &name,
  Email: &email,
  Password: &password,
}).Exec()

# generated mutation
mutation {
  createUser(data: {
    name: "Alice"
    email: "alice@prisma.io"
    password: "IlikeTurtles"
  }) {
    id
    name
    email
    password
  }
}

目前暂时没有。

检查是否具有特定ID存在的用户:


userExists := client.Exists.User(&prisma.UserWhereUniqueInput{
  ID: "cjli6tko8005t0a23fid7kke7",
})

该Prisma的client,你可以直接使用$request方法发送GraphQL Query和Mutation到你的Prisma service:


GraphQL(query string, variables map[string]interface{}) (map[string]interface{}, error)

由于GraphQL操作传递无类型(作为一个普通字符串),返回的承诺的类型是any

查询单个用户:


query := `
  query {
    user(id: "cjcdi63j80adw0146z7r59bn5") {
      id
      name
    }
  }
`
result := client.GraphQL(query, nil)
// sample result:
// map[data:[map[user:[map[id:cjcdi63j80adw0146z7r59bn5 name:Sarah]]]]]

使用variables查询单个用户:


query := `
  query ($id: ID!){
    user(id: $id) {
      id
      name
    }
  }
`
variables := map[string]interface{}{
  "id": "cjcdi63j80adw0146z7r59bn5",
result := client.GraphQL(query, variables)
// sample result:
// map[data:[map[user:[map[id:cjcdi63j80adw0146z7r59bn5 name:Sarah]]]]]

Creating新用户:


mutation := `
  mutation ($name: String!){
    createUser(name: $name) {
      id
      name
    }
  }
`
variables := map[string]interface{}{ "name": "Alice" }
result := client.GraphQL(mutation, variables)
// sample result:
// map[data:[map[createUser:[map[id:cjlhqfbfa003t0a23rhzjragl name:Alice]]]]]
//{ "数据":{ "的createUser":{ "ID": "cjlhqfbfa003t0a23rhzjragl", "名": "爱丽丝"}}}

下一节是Prisma概念,来深入理解它。

深入理解Prisma