Next.js应用中AI聊天记录无法持久化到PostgreSQL问题排查
Next.js聊天消息无法持久化到PostgreSQL的问题排查与修复
问题现象
在Next.js应用中发送AI聊天消息后,控制台日志显示用户消息和AI回复已成功保存到PostgreSQL,但刷新页面后所有聊天记录消失。
核心问题排查与解决方案
1. 消息查询API字段映射错误
你的ChatComponent通过useQuery调用/api/get-messages获取历史消息,但如果该API没有正确将数据库字段转换为ai库的Message类型,会导致刷新后无法加载记录。
修复方案:
实现/api/get-messages路由时,需将数据库的messageContent字段映射为Message类型的content字段:
// app/api/get-messages/route.ts import { db } from '@/lib/db'; import { messages } from '@/lib/db/schema'; import { eq } from 'drizzle-orm'; import { NextResponse } from 'next/server'; import { Message } from 'ai'; export async function POST(req: Request) { const chatId = await req.json(); const rawMessages = await db .select() .from(messages) .where(eq(messages.chatId, chatId)) .orderBy(messages.createdAt); // 转换为ai库要求的Message格式 const formattedMessages: Message[] = rawMessages.map(msg => ({ role: msg.role, content: msg.messageContent })); return NextResponse.json(formattedMessages); }
2. Edge Runtime异步插入中断风险
你的/api/chat路由使用了edge runtime,虽然日志显示插入成功,但Edge环境的请求生命周期限制可能导致异步插入操作未完全执行就被终止。
修复方案:
- 临时移除
export const runtime = 'edge',改用默认Node.js runtime测试是否能正常持久化; - 若必须使用Edge Runtime,确保数据库连接字符串适配Edge环境(如Vercel Postgres的专用连接串),并在插入后添加查询验证:
onStart: async () => { await db.insert(_messages).values({ chatId, messageContent: lastmessage.content, role: "user" }); // 验证插入结果 const latestMsg = await db.select().from(_messages).where(eq(_messages.chatId, chatId)).orderBy(_messages.createdAt.desc()).limit(1); console.log("确认用户消息插入:", latestMsg); }, onCompletion: async (completion) => { await db.insert(_messages).values({ chatId, messageContent: completion, role: "system" }); const latestAIMsg = await db.select().from(_messages).where(eq(_messages.chatId, chatId)).orderBy(_messages.createdAt.desc()).limit(1); console.log("确认AI消息插入:", latestAIMsg); }
3. React Query缓存未主动刷新
新消息插入数据库后,React Query的缓存未更新,可能导致页面刷新前数据不一致(虽然你的问题是刷新后消失,但此步骤可确保数据同步)。
修复方案:
在ChatComponent中添加缓存刷新逻辑:
// 引入useQueryClient import { useQueryClient } from '@tanstack/react-query'; const ChatComponent = ({chatId}: Props) => { const queryClient = useQueryClient(); const { input, handleInputChange, handleSubmit, messages } = useChat({ api: '/api/chat', body: { chatId }, initialMessages: Array.isArray(data) ? data : [], onSuccess: () => { // 刷新聊天记录缓存 queryClient.invalidateQueries({ queryKey: ["chat", chatId] }); } }); // ...其余代码 }
内容的提问来源于stack exchange,提问作者Haroon
相关产品推荐
相关产品推荐

