restore-guid-field.ts 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /**
  2. * 恢复 GroupChat.guid 字段并回填数据
  3. * 线上旧架构代码仍在使用 guid 做多租户隔离,误删除导致所有按 guid 查询的 SQL 报错 42703
  4. *
  5. * 用法: cd backend && npx tsx scripts/restore-guid-field.ts
  6. */
  7. import 'dotenv/config';
  8. import Parse from '../src/db/parse-client.js';
  9. const GUID = process.env.QIWE_GUID || 'B8591A9D-B540-44F9-9D74-B2EF5B419EAA';
  10. async function main(): Promise<void> {
  11. console.log(`=== 恢复 GroupChat.guid 字段 ===`);
  12. console.log(`GUID: ${GUID}\n`);
  13. // 1. 检查字段是否已存在
  14. const schemas = await Parse.Schema.all({ useMasterKey: true });
  15. const groupChatSchema = schemas.find((s: any) => s.className === 'GroupChat');
  16. if (!groupChatSchema) {
  17. console.error('❌ GroupChat 表不存在');
  18. process.exit(1);
  19. }
  20. const existingFields = Object.keys(groupChatSchema.fields).filter((k: string) => !k.startsWith('_'));
  21. console.log(`当前 GroupChat 字段: ${existingFields.join(', ')}`);
  22. if (existingFields.includes('guid')) {
  23. console.log('\n✅ guid 字段已存在,跳过 schema 更新');
  24. } else {
  25. // 2. 添加 guid 字段
  26. const schema = new Parse.Schema('GroupChat');
  27. schema.addField('guid', 'String');
  28. await schema.update({ useMasterKey: true });
  29. console.log('\n✅ 已添加 guid (String) 字段到 GroupChat');
  30. }
  31. // 3. 回填所有缺少 guid 的记录
  32. console.log('\n开始回填数据...');
  33. const q = new Parse.Query('GroupChat');
  34. q.doesNotExist('guid');
  35. q.limit(500);
  36. const groups = await q.find({ useMasterKey: true });
  37. console.log(`找到 ${groups.length} 条缺少 guid 的记录`);
  38. if (groups.length > 0) {
  39. const toSave: Parse.Object[] = [];
  40. for (const g of groups) {
  41. g.set('guid', GUID);
  42. toSave.push(g);
  43. }
  44. // 分批保存
  45. for (let i = 0; i < toSave.length; i += 100) {
  46. const batch = toSave.slice(i, i + 100);
  47. await Parse.Object.saveAll(batch, { useMasterKey: true });
  48. console.log(` 已回填 ${Math.min(i + 100, toSave.length)}/${toSave.length}`);
  49. }
  50. }
  51. // 4. 验证
  52. const verifyQ = new Parse.Query('GroupChat');
  53. verifyQ.equalTo('guid', GUID);
  54. verifyQ.limit(1);
  55. const test = await verifyQ.first({ useMasterKey: true });
  56. if (test) {
  57. console.log(`\n✅ 验证通过: 成功查询到 guid='${GUID}' 的记录 (roomId=${test.get('roomId')})`);
  58. } else {
  59. console.log('\n⚠️ 验证失败: 未查询到匹配记录');
  60. }
  61. console.log('\n✅ 恢复完成!');
  62. }
  63. main().catch((err) => {
  64. console.error('❌ 失败:', err);
  65. process.exit(1);
  66. });