- 后端
- 数据库
- GraphQL
【免费下载链接】prisma1
💾 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL & MongoDB) [deprecated]
本教程面向已拥有运行中 Prisma 服务的开发者,讲解如何在一个轻量 Node 脚本中,通过prisma-binding生成的类型化 API(即Prisma bindings)完成对 Prisma 服务的查询(query)、变更(mutation)与存在性检查(exists)等操作。读完本文,你将掌握从数据模型更新、项目目录搭建、GraphQL schema 下载,到编写并运行可复用的 Node 访问脚本的完整链路,并能理解 Prisma binding 底层如何基于 GraphQL schema 动态生成调用接口。
准备工作:你需要一个运行中的 Prisma 服务
本教程假设你已拥有一个可访问的 Prisma 服务,因此开始之前,请确保手里有该服务的endpoint(端点地址)。如果你还不清楚如何快速搭建自己的 Prisma 服务,可以参考仓库中以下教程(对应docs/1.13/03-Tutorials2/01-Setup-Prisma目录):
- 在 Demo server 上设置 Prisma:使用 Prisma Cloud 托管的免费演示环境,适合学习、原型与开发,但存在限流与存储上限,不建议用于生产。
- 使用新的 MySQL 数据库设置 Prisma
- 使用新的 Postgres 数据库设置 Prisma
- 连接你自己的空 MySQL 数据库设置 Prisma
- 连接你自己的空 Postgres 数据库设置 Prisma
提示:教程中的每一步操作都带有编号标记,避免遗漏;如果你只关心操作步骤本身,可以直接按指令逐步执行。
Step 1:更新数据模型
首先确保你的 Prisma 服务具有本教程后续步骤所需的数据模型。本教程假定你的数据模型存放在单一文件datamodel.graphql中,如果实际布局不同,请相应调整。
操作 1:打开datamodel.graphql,将其内容更新为:
type User { id: ID! @unique name: String! posts: [Post!]! } type Post { id: ID! @unique title: String! content: String! published: Boolean! @default(value: "false") author: User! }操作 2:保存文件后,打开终端并进入 Prisma 服务根目录(即prisma.yml所在目录),运行以下命令更新其 GraphQL API:
prisma deploy更新后,Prisma 服务的 GraphQL API 将为User与Post两种类型暴露完整的 CRUD 操作,同时允许你修改二者之间的关系(relation):一个User拥有多条Post(posts: [Post!]!),每条Post又必须归属一个User(author: User!)。
从源码看:prisma deploy之后发生了什么
prisma deploy会依据prisma.yml中的配置将数据模型同步到 Prisma 服务,并重新生成对应的 GraphQL API。这里值得一提的细节是@default(value: "false")指令——它让published字段在创建Post时自动获得默认值false,因此后续脚本创建文章时无需显式传入该字段。这一点在 Step 4 的示例输出中可以直接看到:createPost返回的对象里published: false,正是默认值起作用的证据。
Step 2:设置项目目录结构
数据模型更新完成后,开始搭建脚本项目。
操作 1:进入一个新目录,在终端中依次执行:
mkdir -p my-node-script/src touch my-node-script/src/index.js cd my-node-script yarn init -y操作 2:接下来,把 Prisma 服务根目录移入my-node-script,并重命名为prisma:
cd .. mkdir my-node-script/prisma mv datamodel.graphql prisma.yml my-node-script/prisma cd my-node-script此时项目结构应如下所示:
. └── my-node-script ├── package.json ├── prisma │ ├── datamodel.graphql │ └── prisma.yml └── src └── index.js操作 3:安装prisma-binding及 GraphQL 核心库:
yarn add prisma-binding graphqlprisma-binding是本教程的主角——它是从 Prisma schema 生成类型化 JavaScript API 的运行时库,graphql则提供底层 schema 解析与文档构建能力。从本仓库的 prisma-client-lib 包 源码可以看到,Prisma绑定实例在构造时会调用buildSchema(typeDefs)解析传入的 schema,并通过BatchedGraphQLClient与SubscriptionClient分别建立查询/变更与订阅通道,这正是"绑定实例 = 面向 Prisma 服务的 JavaScript SDK"这一说法的实现基础。
Step 3:下载 Prisma database schema
下一步是把 Prisma GraphQL API 的 schema(即Prisma database schema)下载到本地项目,供 Prisma binding 指向使用。该操作借助 GraphQL CLI 与 GraphQL Config 完成。
操作 1:全局安装 GraphQL CLI:
yarn global add graphql-cli操作 2:在my-node-script目录(服务根目录)创建.graphqlconfig.yml:
touch .graphqlconfig.yml操作 3:向其中写入以下内容,把 Prisma 的 GraphQL API 定义为一个project:
projects: prisma: schemaPath: src/generated/prisma.graphql extensions: prisma: prisma/prisma.yml此文件提供的信息会被 GraphQL CLI 以及 GraphQL Playground 共同使用:schemaPath指定下载后 schema 的落盘位置,extensions.prisma则指向你的prisma.yml,让 CLI 知道从哪里读取 endpoint 等连接信息。
操作 4:运行以下命令,将 Prisma database schema 下载到src/generated/prisma.graphql:
graphql get-schema下载完成后,定义了你数据库完整 CRUD API 的 Prisma database schema 就位于projects.prisma.schemaPath属性指定的位置(即src/generated/prisma.graphql)。
💡Pro tip:如果你希望每次部署(例如更新数据模型)后 schema 都自动刷新,可以在
prisma.yml中添加如下post-deployment hook。hooks是prisma.yml中可选的配置项,用于在 Prisma CLI 特定动作前后执行终端命令,当前可用的是post-deploy(在prisma deploy之后触发),其类型为对象,键名与可用钩子一一对应。更完整的说明见 prisma.yml 配置参考:
hooks: post-deploy: - graphql get-schema -p prisma仓库中 YAML-Structure.md 还给出了post-deploy同时执行多个任务的示例,例如打印部署完成信息、为dbproject 下载 schema、执行代码生成等,读者可自行参考扩展。
Step 4:使用 Prisma binding 发送查询与变更
本步骤将正式使用 Prisma binding 与你的 Prisma 服务通信。
首先,通过指向上一步下载的 schema 来实例化一个 Prisma binding;由于绑定实例需要连接到你的 Prisma API,因此还必须提供 Prisma API 的endpoint(该值可从prisma/prisma.yml中查到)。绑定实例充当 Prisma 服务的"JavaScript SDK",你可以调用其 API 向 Prisma 数据库发送查询与变更。
操作 1:将以下代码写入src/index.js。它创建了一个Prisma绑定实例,并依次执行创建用户、查询用户、创建文章、更新文章、级联查询以及批量删除等操作:
⚠️Important:务必把
__YOUR_PRISMA_ENDPOINT__替换为你的 Prisma endpoint,它存储在prisma/prisma.yml中。
const { Prisma } = require("prisma-binding") const prisma = new Prisma({ typeDefs: "src/generated/prisma.graphql", endpoint: "__YOUR_PRISMA_ENDPOINT__" }) prisma.mutation .createUser({ data: { name: "Alice" } }, "{ id name }") .then(console.log) // { id: 'cjhcidn31c88i0b62zp4tdemt', name: 'Alice' } .then(() => prisma.query.users(null, "{ id name }")) .then(response => { console.log(response) // [ { id: 'cjhcidn31c88i0b62zp4tdemt', name: 'Alice' } ] return prisma.mutation.createPost({ data: { title: "Prisma rocks!", content: "Prisma rocks!", author: { connect: { id: response[0].id } } } }) }) .then(response => { console.log(response) /* { id: 'cjhcidoo5c8af0b62kv4dtv3c', title: 'Prisma rocks!', content: 'Prisma rocks!', published: false } */ return prisma.mutation.updatePost({ where: { id: response.id }, data: { published: true } }) }) .then(console.log) /* { id: 'cjhcidoo5c8af0b62kv4dtv3c', title: 'Prisma rocks!', content: 'Prisma rocks!', published: true } */ .then(() => prisma.query.users(null, "{ id posts { title } }")) .then(console.log) // [ { id: 'cjhcidn31c88i0b62zp4tdemt', posts: [ [Object] ] } ] .then(() => prisma.mutation.deleteManyPosts()) .then(console.log) // { count: 1 } .then(() => prisma.mutation.deleteManyUsers()) .then(console.log) // { count: 1 }操作 2:运行脚本,观察终端打印的查询结果:
node src/index.js理解绑定 API 的调用约定
从代码可以看出 Prisma binding 的两个关键调用形态:
query/mutation:每个数据模型类型对应一组方法,例如users、createUser、updatePost、deleteManyPosts。方法签名通常为(args, selectionSet)——第一个参数是 GraphQL 变量(如data、where),第二个参数是你想要返回的字段选择集(如"{ id name }")。绑定实例在内部会基于下载的 schema 解析出对应字段与类型,动态生成 GraphQL 文档后发送请求。- 关系写入:创建文章时通过
author: { connect: { id: ... } }关联已存在的User,这是 Prisma 处理关系型嵌套写入的标准语法——connect表示"连接到已有节点",而create则表示"同时新建关联节点"。
从 Client.ts 的实现看,query、mutation、$subscribe、$graphql、$exists等属性均在构造阶段通过buildMethods()等内部方法构建:每个调用先记录为一组 "instructions",再经getDocumentForInstructions生成完整 GraphQL 文档并交由底层的BatchedGraphQLClient发送;同时它支持通过secret配置签发 JWT 令牌,以Authorization: Bearer <token>请求头完成鉴权。也就是说,你使用的"类型化 SDK"本质上是基于 schema 动态生成的、对 GraphQL 请求的封装层。
Step 5:使用exists检查特定节点的存在性
除了query和mutation,Prisma binding 还提供了一个便捷属性exists,用于检查数据库中是否存在满足特定条件的节点。exists为数据模型中的每个类型暴露一个函数,函数名与类型同名(本例即prisma.exists.User(filter)和prisma.exists.Post(filter))。这些函数接收filter参数,始终返回true或false。
因为Step 1创建的数据模型包含User与Post两个模型,Prisma 便生成了exists.User与exists.Post。
操作 1:将以下代码写入src/index.js。它实例化 Prisma binding,创建用户与文章后使用exists验证节点存在性,删除数据后再验证节点已不存在:
⚠️Important:务必把
__YOUR_PRISMA_ENDPOINT__替换为你的 Prisma endpoint,它存储在prisma/prisma.yml中。
const { Prisma } = require("prisma-binding") const prisma = new Prisma({ typeDefs: "src/generated/prisma.graphql", endpoint: "__YOUR_PRISMA_ENDPOINT__" }) prisma.mutation .createUser({ data: { name: "Alice" } }, "{ id name }") .then(response => { return prisma.mutation.createPost({ data: { title: "Prisma rocks!", content: "Prisma rocks!", author: { connect: { id: response.id } } } }) }) .then(() => prisma.exists.User({ name: "Alice" })) .then(response => console.log(response)) // true .then(() => prisma.exists.Post({ title: "Prisma rocks" })) .then(response => console.log(response)) // true .then(() => prisma.mutation.deleteManyPosts()) .then(() => prisma.mutation.deleteManyUsers()) .then(() => prisma.exists.Post({ title: "Prisma rocks" })) .then(response => console.log(response)) // false .then(() => prisma.exists.User({ name: "Alice" })) .then(console.log) // false操作 2:运行脚本,观察终端打印的结果:
node src/index.jsexists的典型用途
exists非常适合在写入前做幂等校验或条件判断,例如"用户名是否已注册""文章标题是否已存在"这类场景。它避免了手写完整的users(where: ...)查询再自行判空的样板代码,返回值语义清晰(布尔值),可直接用于业务分支。在仓库的 Client.ts 中,$exists由buildExists()构建,内部同样基于 schema 中每个类型的where过滤参数生成对应查询,其实现与query/mutation共享同一套指令与文档生成管线。
Step 6:以字符串形式发送原始查询与变更
Prisma binding 还允许你通过request属性,把完整的查询/变更以字符串形式直接发给 Prisma 服务。这种方式更为冗长——你需要拼写完整操作,且响应会多一层开销:因为返回结果会以查询/变更的名称作为顶层 key 包裹。
说明:Prisma binding 的
request底层使用graphql-request,因此与它拥有相同的 API 形态,即request(query, variables?)。
操作 1:将src/index.js的内容替换为以下代码:
⚠️Important:务必把
__YOUR_PRISMA_ENDPOINT__替换为你的 Prisma endpoint,它存储在prisma/prisma.yml中。
const { Prisma } = require("prisma-binding") const prisma = new Prisma({ typeDefs: "src/generated/prisma.graphql", endpoint: "__YOUR_PRISMA_ENDPOINT__" }) const query = ` { users { id name } } ` const mutation = ` mutation CreateUser($name: String!) { createUser(data: { name: $name }) { id name } } ` const variables = { name: 'Bob' } prisma.mutation .createUser({ data: { name: 'Alice' } }, '{ id name }') .then(console.log) // { id: 'cjhcijh30cgww0b622rwkkvbo', name: 'Alice' } .then(() => prisma.request(mutation, variables)) .then(console.log) // { createUser: { id: 'cjhcijjndch0d0b62qux6o52a', name: 'Bob' } } .then(() => prisma.query.users(null, '{ id name }')) .then(console.log) /* [ { id: 'cjhciiacxcf850b62mcuaa3uz', name: 'Alice' }, { id: 'cjhcijjndch0d0b62qux6o52a', name: 'Bob' } ] */ .then(() => prisma.request(query)) .then(console.log) /* { users: [ { id: 'cjhciiacxcf850b62mcuaa3uz', name: 'Alice' }, { id: 'cjhcijjndch0d0b62qux6o52a', name: 'Bob' } ] } */操作 2:运行脚本,观察终端打印的结果:
node src/index.js对比:request与类型化 API
对比 Step 4 与 Step 6 的输出可以清晰看到差异:
- 类型化调用(
prisma.query.users、prisma.mutation.createUser)返回的是字段选择集直接对应的结果,结构扁平、无需关心操作名。 - 原始
request调用则需要手写完整 GraphQL 文档(可含变量定义与操作名),其响应以操作名作为顶层 key(如{ createUser: {...} }、{ users: [...] }),并且需要自行把变量作为第二个参数传入。
因此,request更适合"有现成 GraphQL 字符串/文档"或"需要动态拼接操作"的场景,而类型化 API 在开发体验与代码可读性上更胜一筹。
小结
本教程带你走完了"用 Node 脚本访问 Prisma 服务"的完整流程:
- 更新数据模型(
datamodel.graphql+prisma deploy),让 Prisma 服务暴露User/Post的 CRUD API; - 搭建项目结构,将 Prisma 服务目录迁入脚本项目,安装
prisma-binding与graphql; - 下载 Prisma database schema(
.graphqlconfig.yml+graphql get-schema),并可选配置post-deployhook 实现自动刷新; - 类型化调用
prisma.query/prisma.mutation完成增删改查与关系连接; - 存在性检查
prisma.exists.User(...)/prisma.exists.Post(...),以布尔值快速判断节点是否存在; - 原始请求
prisma.request(query, variables),以字符串形式发送完整 GraphQL 文档。
这套能力可以无缝嵌入定时任务、数据迁移脚本、CI 校验、批量数据处理等场景,让 Node 脚本成为 Prisma 数据库的"一等公民"。对绑定实例内部机制感兴趣的读者,可继续阅读本仓库 prisma-client-lib 包 的源码,深入理解 schema 解析、指令生成与请求批处理的具体实现。
- 后端
- 数据库
- GraphQL
【免费下载链接】prisma1
💾 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL & MongoDB) [deprecated]
相关推荐
使用 Prisma Bindings 从 Node 脚本访问 Prisma 服务:完整实战教程
使用 Prisma Bindings 从 Node 脚本访问 Prisma 服务:完整实战教程 本教程基于 Prisma 1.x 的官方操作手册,完整演示如何从
后端数据库GraphQL使用 Prisma Bindings 在 Node 脚本中访问 Prisma 服务:完整实操指南
使用 Prisma Bindings 在 Node 脚本中访问 Prisma 服务:完整实操指南 本指南面向已经部署好 Prisma 服务的开发者,讲解如何从零
后端数据库GraphQL在 Node 脚本中通过 Prisma Bindings 访问 Prisma 服务:从零搭建可运行的查询与变更客户端
在 Node 脚本中通过 Prisma Bindings 访问 Prisma 服务:从零搭建可运行的查询与变更客户端 本篇技术指南讲解如何在一个普通 Node.
后端数据库GraphQL
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考