Convex 数据库是一个开源的响应式后端即服务(Backend-as-a-Service)平台,专为现代全栈应用开发设计。它集成了数据库、服务器函数、文件存储、实时同步、身份验证等功能,开发者只需编写 TypeScript 代码即可构建高性能、实时更新的应用。
集成convex
官方指南:docs.convex.dev/quickstart/…
安装依赖
pnpm install convex
运行convex
pnpm dlx convex dev
结束后项目根目录下会生成配置文件:.env.local ,并且看板会生成新的convex项目:
添加测试数据
这是一个测试
sampleData.jsonl
{"text": "Buy groceries", "isCompleted": true}
{"text": "Go for a swim", "isCompleted": true}
{"text": "Integrate Convex", "isCompleted": false}
将数据导入数据库:pnpm dlx convex import --table tasks sampleData.jsonl
创建查询请求:convex/tasks.ts
import { query } from "./_generated/server";
export const get = query({
args: {},
handler: async (ctx) => {
return await ctx.db.query("tasks").collect();
},
});
创建ConvexClientProvider
创建 app/providers/ConvexClientProvider.tsx
"use client";
import { ConvexProvider, ConvexReactClient } from "convex/react";
import { ReactNode } from "react";
const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);
export function ConvexClientProvider({ children }: { children: ReactNode }) {
return <ConvexProvider client={convex}>{children}</ConvexProvider>;
}
在 app/layout.tsx 中使用:
<ConvexClientProvider>
{children}
</ConvexClientProvider>
展示数据
app/page.tsx
"use client";
import { useQuery } from "convex/react";
import { api } from "../../convex/_generated/api";
export default function Home() {
const tasks = useQuery(api.tasks.get);
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
{tasks?.map(({ _id, text }) => <div key={_id}>{text}</div>)}
</main>
);
}
启动服务,发现数据显示在页面上,到此convex集成完毕,可以把测试数据删掉。
测试完就可以删除所有的数据。
添加表格
创建 convex/schema.ts 文件,所有的表格都定义在里面。
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
// messages 表
messages: defineTable({
body: v.string(),
user: v.id("users"),
}),
// users 表
users: defineTable({
name: v.string(),
tokenIdentifier: v.string(),
}).index("by_token", ["tokenIdentifier"]),
});
定义CRUD
创建 convex/files.ts 文件,针对 files 表进行增删改查操作。
convex 提供了 query 和 mutation 函数,query 只是用来查询操作,mutaion 则进行增删改。
以下是一个示例:
import { v } from "convex/values";
import { mutation, query } from "./_generated/server";
export const getFiles = query({
args: {},
handler: async (ctx, args) => {
return await ctx.db.query("files").collect();
},
});
export const create = mutation({
args: {
telegramFileId: v.string(),
telegramMessageId: v.number(),
name: v.string(),
size: v.number(),
type: v.string(),
},
handler: async (ctx, args) => {
await ctx.db.insert("files", {
telegramFileId: args.telegramFileId,
telegramMessageId: args.telegramMessageId,
name: args.name,
size: args.size,
type: args.type,
});
},
});
export const remove = mutation({
args: {
telegramMessageId: v.number(),
},
handler: async (ctx, args) => {
const file = await ctx.db
.query("files")
.withIndex("by_telegramMessageId", (q) =>
q.eq("telegramMessageId", args.telegramMessageId),
)
.unique();
if (file) {
await ctx.db.delete(file._id);
}
},
});
调用定义的CRUD
客户端调用
即声明了 use client 的地方调用。
查询使用 useQuery,增删改使用 useMutation。
查询操作:
const users = useQuery(api.users.get);
// 如果有参数的话
const users = useQuery(api.users.get, {
id: xxx
});
修改操作:
const createUser = useMutation(api.users.create);
await createUser({ name: '张三', age: 12 });
服务端调用
服务端则使用 fetchMutation 和 fetchQuery。
await fetchMutation(api.files.remove, {
telegramMessageId: Number(messageId),
});
更多操作还在探索