convex-backend 函数目录入门:从 README 引导到 Query/Mutation 与分页实战
数据库后端【免费下载链接】convex-backendThe open-source reactive database for app developers项目地址https://gitcode.com/gh_mirrors/co/convex-backend点击查看免费下载导读本文围绕npm-packages/private-demos/pagination-visualization/convex/README.md展开它是 Convex 项目中每个convex/函数目录的标准引导文档告诉你如何编写带参数校验的 query 查询函数与 mutation 变更函数、如何把函数引用到 React 组件中使用以及如何用 Convex CLI 推送函数到部署环境。我们将以这份引导文档为主体结合pagination-visualization演示项目的真实源码与convexnpm 包中的usePaginatedQuery实现讲透 query/mutation 的完整写法、_generated类型生成机制以及在此基础上进阶的分页查询原理。读完本文你将能独立编写、校验、调用和部署自己的 Convex 后端函数。一、convex/函数目录与引导文档的定位在 Convex 项目中你的所有后端函数都集中放在根目录下的convex/文件夹里。pagination-visualization演示项目的目录结构为npm-packages/private-demos/pagination-visualization/ ├── convex/ # 后端函数目录 │ ├── _generated/ # CLI 自动生成的类型与 API 引用 │ ├── README.md # 本文所依据的引导文档 │ ├── names.ts # 真实的 query/mutation 函数 │ └── schema.ts # 可选的数据库 schema 定义 ├── src/ # 前端 React 代码 │ ├── App.tsx # 分页可视化界面 │ └── main.tsx └── package.json # 依赖与启动脚本README.md的第一行 Welcome to your Convex functions directory! 明确点出了它的身份——这是脚手架生成的标准引导页告诉新项目开发者在哪里写函数convex/目录内的任意.ts文件query 和 mutation 分别长什么样、怎么在 React 里调用如何用 CLI 把函数部署到远端。它提到的两处官方文档入口docs.convex.dev/functions、docs.convex.dev/database/reading-data对应着本仓库中 convex 包 等源码注释里反复引用的同名文档。也就是说这份 README 是整个函数开发流程的目录页而本仓库里的源码则是它背后完整的实现。二、Query 函数从定义到 React 调用2.1 带参数校验的 query 定义README 给出的标准 query 模板如下原文完整继承// convex/myFunctions.ts import { query } from ./_generated/server; import { v } from convex/values; export const myQueryFunction query({ // Validators for arguments. args: { first: v.number(), second: v.string(), }, // Function implementation. handler: async (ctx, args) { // Read the database as many times as you need here. const documents await ctx.db.query(tablename).collect(); // Arguments passed from the client are properties of the args object. console.log(args.first, args.second); // Write arbitrary JavaScript here: filter, aggregate, build derived data, // remove non-public properties, or create new objects. return documents; }, });这里有几个值得展开的要点1query来自./_generated/server而不是从convex包直接导入。_generated/目录由 Convex CLI 自动生成它在编译期把你的函数与类型系统连接起来。该演示项目的 convex/_generated/server.d.ts 就是生成产物之一你可以打开查看其中的query、mutation类型签名。2args中的 Validator 是参数校验器。v.number()、v.string()来自convex/values用于在运行时校验客户端传入的参数。README 注释里说Validators for arguments——如果客户端传入的类型不匹配函数会直接拒绝执行并返回错误。这是 Convex 相比普通 JS 后端的显著差异参数契约在函数定义处就强制执行。在 npm-packages/convex/src/values 中可以看到完整的校验器体系包括v.id()、v.array()、v.union()、v.optional()等。3handler的第一个参数ctx是执行上下文。通过ctx.db可以查询数据库。ctx.db.query(tablename).collect()返回表中全部文档README 注释特别说明Read the database as many times as you need here——即 handler 内可以自由多次读取数据库。2.2 在 React 组件中使用 queryREADME 给出了对应的 React 端用法const data useQuery(api.myFunctions.myQueryFunction, { first: 10, second: hello, });要点是useQuery的第一个参数不是字符串函数名而是api.myFunctions.myQueryFunction——这个api对象同样来自./_generated/api如演示项目中的 convex/_generated/api.ts它提供全类型安全的函数引用函数名拼错、参数类型不匹配都会在编译期报错。useQuery是响应式的当first、second对应的查询结果在服务端发生变化时组件会自动重新渲染拿到最新数据无需手动刷新。三、Mutation 函数写入数据库的正确姿势3.1 标准 mutation 模板README 给出的 mutation 模板原文完整继承// convex/myFunctions.ts import { mutation } from ./_generated/server; import { v } from convex/values; export const myMutationFunction mutation({ // Validators for arguments. args: { first: v.string(), second: v.string(), }, // Function implementation. handler: async (ctx, args) { // Insert or modify documents in the database here. // Mutations can also read from the database like queries. const message { body: args.first, author: args.second }; const id await ctx.db.insert(messages, message); // Optionally, return a value from your mutation. return await ctx.db.get(messages, id); }, });与 query 的关键差异mutation 用于写入数据ctx.db.insert插入文档、ctx.db.delete删除文档同时 mutation 内也可以像 query 一样读取数据库README 注释明示 Mutations can also read from the database like queriesmutation 的 handler 执行在事务中要么全部生效要么全部回滚mutation 可以返回一个值上例返回刚插入的文档也可以什么都不返回。3.2 在 React 中调用 mutationREADME 给出的两种调用方式const mutation useMutation(api.myFunctions.myMutationFunction); function handleButtonPress() { // fire and forget, the most common way to use mutations mutation({ first: Hello!, second: me }); // OR // use the result once the mutation has completed mutation({ first: Hello!, second: me }).then((result) console.log(result), ); }两种方式的取舍在 README 注释里说得很清楚fire and forget直接调用不等待最常见的方式适用于不需要关心结果的场景如记录一次点击等待完成.then(...)获取返回值当 UI 需要依赖 mutation 的执行结果如展示新文档 ID、跳转页面时使用。注意useMutation返回的mutation本身就是一个可调用函数它的签名与后端myMutationFunction的args严格对应。四、进阶示例pagination-visualization 如何落地这些模板引导文档教你写第一个 query/mutation而演示项目则把它们用到了真实场景。查看 convex/names.ts可以看到模板的实战变形4.1 一个真正的 query带索引的分页查询export const getPeople query({ args: { paginationOpts: paginationOptsValidator, }, handler: async ({ db }, { paginationOpts }) { return await db .query(people) .withIndex(by_name) .paginate(paginationOpts); }, });与引导模板相比这里出现了三个新概念paginationOptsValidator来自convex/server分页参数校验器定义在 npm-packages/convex/src/server/pagination.ts结构为{ numItems, cursor, endCursor?, id?, maximumRowsRead?, maximumBytesRead? }.withIndex(by_name)按 convex/schema.ts 中声明的people表索引查询export default defineSchema({ people: defineTable({ name: v.string(), }).index(by_name, [name]), });schema 文件是可选的README 注释 The schema is entirely optional. You can delete this file and the app will continue to work.它的价值在于提供更精确的 TypeScript 类型并声明查询索引.paginate(paginationOpts)服务端分页 API。它的底层实现会发起1.0/queryPage异步系统调用携带cursor、endCursor、pageSize、maximumRowsRead、maximumBytesRead等参数见 query_impl.ts。4.2 一组真正的 mutationseed / addPerson / deletePersonexport const seed mutation({ args: { names: v.array(v.string()) }, handler: async ({ db }, { names }) { // Remove all existing rows for await (const row of db.query(people)) { await db.delete(row._id); } for (const name of names) { await db.insert(people, { name }); } }, }); export const addPerson mutation({ args: { name: v.string() }, handler: async ({ db }, { name }) { await db.insert(people, { name }); }, }); export const deletePerson mutation({ args: { id: v.id(people) }, handler: async ({ db }, { id }) { await db.delete(id); }, });这三个 mutation 演示了引导模板之外的能力v.array(v.string())表示参数是字符串数组v.id(people)表示参数必须是people表的合法文档 ID类型校验直接与 schema 关联在 mutation 中用for await遍历并删除全部旧数据实现了先清空再灌入的 seed 逻辑——这正是引导文档所说mutation 内也可以读取数据库的实际应用。在 src/App.tsx 中它们通过useMutation(api.names.addPerson)、useMutation(api.names.deletePerson)、useMutation(api.names.seed)接入 UI点击 Seed 按钮会随机抽取 20 个名字灌入数据库。五、深入分页引导模板之外的完整链路pagination-visualization的核心价值是把分页过程中每一页到底发生了什么可视化出来。这需要理解前端 hook 与服务端 API 的配合。5.1 客户端usePaginatedQuery与usePaginatedQueryInternal前端核心代码在 src/App.tsxconst { user: { results, status, loadMore }, internal, } usePaginatedQueryInternal( api.names.getPeople, {}, { initialNumItems: 5, [includePage]: true }, );这里用到的是convex/react导出的内部版本usePaginatedQueryInternalusePaginatedQuery的底层实现见 use_paginated_query.ts。普通项目用公开的usePaginatedQuery即可const { results, status, isLoading, loadMore } usePaginatedQuery( api.messages.list, { channel: #general }, { initialNumItems: 5 }, );usePaginatedQuery会做三件事注入分页参数自动在 args 里加上paginationOpts: { numItems, cursor, id }其中cursor: null表示从第一页开始见源码 L231-L237拼接所有页把已加载的每一页page结果拼成一个完整列表results管理状态机返回statusLoadingFirstPage/CanLoadMore/LoadingMore/Exhausted和loadMore(n)回调。5.2 分页状态机与异常恢复从 use_paginated_query.ts 的状态构造逻辑可以看到完整的状态定义statusisLoading含义loadMore 行为LoadingFirstPagetrue正在加载第一页noopCanLoadMorefalse还有更多数据可加载发起下一页请求LoadingMoretrue正在加载后续页noopExhaustedfalse已到列表末尾noopError内部版本false查询出错noop另外当服务端返回InvalidCursor错误时例如分页所依赖的数据在读取过程中发生了变化hook 会主动重置分页状态从头开始见源码 L290-L310并在 logger 中打印警告。每个分页会话还会携带一个自增的paginationId作为 cache-buster保证新会话不会错误复用旧的订阅结果见 L452-L480。5.3 服务端PaginationResult与页面拆分服务端.paginate()的返回结构PaginationResult定义在 pagination.tsinterface PaginationResultT { page: T[]; // 本页结果 isDone: boolean; // 是否已到末尾 continueCursor: Cursor; // 下一页的游标 splitCursor?: Cursor | null; // 拆分本页为两半的游标 pageStatus?: SplitRecommended | SplitRequired | null; }其中pageStatus是响应式分页的进阶机制当一页读取的数据量过大时服务端可能返回SplitRecommended建议拆分甚至SplitRequired页面可能不完整必须拆分。客户端检测到这些信号后会调用splitQuery把这一页拆成(cursor, splitCursor]和(splitCursor, continueCursor]两个半页并行加载见 L60-L96。pagination-visualization的 App.tsx 正是把这些页面的边界、每个分页参数numItems、cursor、endCursor、id等逐条渲染出来并用颜色标记游标让你直观看到响应式数据变化时分页如何自动调整——这是理解endCursor参数作用确保数据变化时页面之间不出现空隙见 pagination.ts的最佳实验场。六、用 Convex CLI 推送与运行README 的最后一段说明了 CLI 的使用方式Use the Convex CLI to push your functions to a deployment. See everything the Convex CLI can do by runningnpx convex -hin your project root directory. To learn more, launch the docs withnpx convex docs.在pagination-visualization项目中实际运行npx convex dev --start vite --open这是 package.json 中定义的dev脚本convex dev会持续监听convex/目录把函数同步到本地开发部署并自动生成_generated/文件--start vite --open则同时启动 Vite 开发服务器并打开浏览器。常用 CLI 命令速查命令作用npx convex -h查看全部 CLI 命令npx convex docs在本地启动官方文档npx convex dev本地开发监听函数变更、同步部署、生成_generatednpx convex dev --once单次同步后退出CI 场景常用npx convex deploy推送函数到生产部署README 特别提示要在project root directory项目根目录运行这些命令——因为 CLI 需要读取根目录下的convex.json与package.json来确定项目配置。七、快速上手清单结合引导文档与演示项目一个完整的新手路径如下初始化项目创建convex/目录放入README.md脚手架会生成与函数文件定义 schema可选在 convex/schema.ts 中用defineSchema/defineTable声明表和索引编写函数query 用query({ args: {...}, handler })写入用mutation({...})参数一律用v校验器声明跑一次 CLInpx convex dev生成_generated/此后 import./_generated/server、../convex/_generated/api均获得类型安全接入前端useQuery(api.xxx, args)读、useMutation(api.xxx)写列表加载用usePaginatedQuery配合initialNumItems与loadMore验证效果对照pagination-visualization的可视化界面loadMore(5)、Seed 按钮、页面边界渲染确认每个status的流转是否符合预期。结语convex/README.md虽然只是一份脚手架引导但它浓缩了 Convex 函数开发的全部核心动作用 Validator 声明参数契约、用ctx.db读写数据、用_generated获得类型安全、用 CLI 完成部署。在此基础上pagination-visualization演示项目把 query/mutation 模板延展成了带索引、带分页、带响应式可视化的完整应用而 use_paginated_query.ts 与 pagination.ts 则揭示了游标、页面拆分与状态机背后的实现细节。从模板到实战再到源码级原理这条路径正是理解 Convex 后端开发的最佳入口。赞分享数据库后端【免费下载链接】convex-backendThe open-source reactive database for app developers项目地址https://gitcode.com/gh_mirrors/co/convex-backend点击查看免费下载相关推荐Convex 函数目录开发指南从零编写 Convex query 与 mutation 函数convex-backend 实战Convex 函数目录开发指南从零编写 Convex query 与 mutation 函数convex backend 实战 本指南以 convex b数据库后端Convex Backend 函数开发入门从 Query 到 Mutation 的类型安全实战指南Convex Backend 函数开发入门从 Query 到 Mutation 的类型安全实战指南 Convex 是一个面向应用开发者的开源响应式数据库其核数据库后端Convex 函数目录入门指南从 Query 到 Mutation 的完整开发实战Convex 函数目录入门指南从 Query 到 Mutation 的完整开发实战 本文以 convex backend 仓库中 tour chat 教程项目数据库后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Flutter库punycoder的鸿蒙适配与国际化域名处理

Flutter库punycoder的鸿蒙适配与国际化域名处理

## 1. 项目背景与核心价值国际化域名(IDN)的出现让非英语用户能够使用母语字符注册和访问网站,但底层DNS系统仍只支持ASCII字符。RFC 3492标准定义的Punycode编码方案解决了这一矛盾,它将Unicode字符串转换为ASCII兼容编码&#x…

2026/10/13 23:50:38 阅读更多 →
Spring Boot医疗预约系统设计与优化实践

Spring Boot医疗预约系统设计与优化实践

1. 项目概述与核心价值医疗资源分配不均和预约效率低下一直是困扰医患双方的核心痛点。这个基于Spring Boot的会员制医疗预约服务管理系统,本质上是通过信息化手段重构传统医疗预约流程。我在实际开发中发现,系统不仅要解决"能预约"的基础需求…

2026/10/13 23:50:38 阅读更多 →
Oracle 19c RAC 在 Linux 7.9 上部署的五大临界点与避坑指南

Oracle 19c RAC 在 Linux 7.9 上部署的五大临界点与避坑指南

简介:本资源是一份面向DBA、Oracle运维工程师及高可用架构学习者的实战部署指南,聚焦Linux 7.9环境下Oracle 19C RAC集群的完整落地实践,解决多节点协同、共享存储配置、ASM磁盘组管理及集群服务启动等核心难点。文档以VMware Workstation Pr…

2026/10/13 23:50:38 阅读更多 →

最新新闻

MFC中种子填充算法的工程实现与避坑指南

MFC中种子填充算法的工程实现与避坑指南

1. 项目概述:为什么在MFC里实现种子填充,远不止“画个实心圆”那么简单你打开《计算机图形学》实验指导书,翻到第5页,“区域填充——种子填充算法(MFC中)”这行字印得工整,旁边还配了个带边界的…

2026/10/14 0:40:54 阅读更多 →
BACnet客户端C#源码实战:从设备发现到属性读写与避坑指南

BACnet客户端C#源码实战:从设备发现到属性读写与避坑指南

简介:一套基于C#编写的BacNet客户端程序源码,面向楼宇自动化(BAS)开发者、工控软件工程师及希望掌握BACnet协议栈的C#程序员。BacNet是楼宇自动化系统的开放通信标准,支持局域网、以太网、Wi-Fi等多种介质;…

2026/10/14 0:40:54 阅读更多 →
【揭秘】淘宝AI购物技术:AI替用户下单,付款链路怎么测?

【揭秘】淘宝AI购物技术:AI替用户下单,付款链路怎么测?

摘要:千问与淘宝打通商品发现、比较、下单和售后后,AI购物不再只是“推荐商品”。本文依据阿里巴巴与支付宝公开资料,把一句自然语言购物需求拆成商品、报价、确认、订单、支付和异步结果六段证据,并给出可运行的行为断言、异常测…

2026/10/14 0:40:54 阅读更多 →
stb_image单头文件图像解码库:从stbi_load到OpenGL纹理上传完整指南

stb_image单头文件图像解码库:从stbi_load到OpenGL纹理上传完整指南

简介:stb_image是一套应用广泛的开源图像处理库资源,面向需要在C/C项目中快速加载JPEG、PNG、BMP、TGA、WebP等多种格式图像的开发者,广泛用于游戏开发、工具软件与教学示例,尤其适合图像处理初学者和寻求轻量级集成的项目。该资源…

2026/10/14 0:40:54 阅读更多 →
通信总线传输速率计算:从时钟频率到有效带宽的完整拆解

通信总线传输速率计算:从时钟频率到有效带宽的完整拆解

1. 通信总线传输速率计算的核心逻辑拆解通信总线传输速率计算这件事,看起来就是套个公式,但我见过太多人在这上面翻车。有人把时钟频率直接当成传输速率,有人算出来带宽对不上实测值,还有人忽略了编码开销导致选型时余量算错。这个…

2026/10/14 0:40:54 阅读更多 →
鄱阳湖2005年1:25万矢量边界数据集(CGCS2000坐标系)

鄱阳湖2005年1:25万矢量边界数据集(CGCS2000坐标系)

简介:本资源为2005–2006年鄱阳湖1:25万精度矢量边界数据集,面向地理信息、生态遥感、水利规划及环境科研领域的高校师生、GIS工程师与政策研究者,提供高精度、可分析的湖泊空间基准底图,支撑湿地演变分析、水位变化建模、洪涝风险…

2026/10/14 0:39:54 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →