cleanup-redundant-fields.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /**
  2. * 清除冗余 String 字段——外键关系统一使用 Pointer
  3. *
  4. * 清除的字段:
  5. * GroupChat: storeId, storeName, communityId, communityName
  6. * Store: districtId, districtName
  7. * Community: storeId, storeName, districtId, districtName
  8. *
  9. * 前置条件: assign-store-ids.ts 已运行,所有 Pointer 字段已就位
  10. * 用法: npx tsx scripts/cleanup-redundant-fields.ts
  11. */
  12. import 'dotenv/config';
  13. import Parse from '../src/db/parse-client.js';
  14. async function main(): Promise<void> {
  15. console.log('[Cleanup] 开始清除冗余 String 字段…\n');
  16. // 1. GroupChat: 移除 storeId, storeName, communityId, communityName
  17. console.log('[Cleanup] 处理 GroupChat…');
  18. const gq = new Parse.Query('GroupChat');
  19. gq.limit(1000);
  20. const groups = await gq.find({ useMasterKey: true });
  21. let gCleaned = 0;
  22. const gToSave: Parse.Object[] = [];
  23. for (const g of groups) {
  24. const hasStorePtr = !!g.get('store');
  25. const hasCommunityPtr = !!g.get('community');
  26. const hasStoreId = g.get('storeId');
  27. const hasStoreName = g.get('storeName');
  28. const hasCommunityId = g.get('communityId');
  29. const hasCommunityName = g.get('communityName');
  30. if (!hasStorePtr && !hasCommunityPtr && !hasStoreId && !hasStoreName && !hasCommunityId && !hasCommunityName) {
  31. continue;
  32. }
  33. // 只在 Pointer 已设置时清除对应的 String 字段
  34. if (hasStorePtr && (hasStoreId || hasStoreName)) {
  35. g.unset('storeId');
  36. g.unset('storeName');
  37. gCleaned++;
  38. }
  39. if (hasCommunityPtr && (hasCommunityId || hasCommunityName)) {
  40. g.unset('communityId');
  41. g.unset('communityName');
  42. gCleaned++;
  43. }
  44. gToSave.push(g);
  45. }
  46. if (gToSave.length > 0) {
  47. for (let i = 0; i < gToSave.length; i += 100) {
  48. await Parse.Object.saveAll(gToSave.slice(i, i + 100), { useMasterKey: true });
  49. }
  50. }
  51. console.log(` GroupChat: ${groups.length} 条, 清除 ${gCleaned} 个冗余字段`);
  52. // 2. Store: 移除 districtId, districtName
  53. console.log('[Cleanup] 处理 Store…');
  54. const sq = new Parse.Query('Store');
  55. sq.limit(500);
  56. const stores = await sq.find({ useMasterKey: true });
  57. let sCleaned = 0;
  58. const sToSave: Parse.Object[] = [];
  59. for (const s of stores) {
  60. const hasDistrictPtr = !!s.get('district');
  61. const hasDistrictId = s.get('districtId');
  62. if (hasDistrictPtr && hasDistrictId !== undefined) {
  63. s.unset('districtId');
  64. s.unset('districtName');
  65. sCleaned++;
  66. sToSave.push(s);
  67. }
  68. }
  69. if (sToSave.length > 0) {
  70. await Parse.Object.saveAll(sToSave, { useMasterKey: true });
  71. }
  72. console.log(` Store: ${stores.length} 条, 清除 ${sCleaned} 个冗余字段`);
  73. // 3. Community: 移除 storeId, storeName, districtId, districtName
  74. console.log('[Cleanup] 处理 Community…');
  75. const cq = new Parse.Query('Community');
  76. cq.limit(500);
  77. const communities = await cq.find({ useMasterKey: true });
  78. let cStoreCleaned = 0;
  79. let cDistrictCleaned = 0;
  80. const cToSave: Parse.Object[] = [];
  81. for (const c of communities) {
  82. let changed = false;
  83. const hasStorePtr = !!c.get('store');
  84. if (hasStorePtr && c.get('storeId') !== undefined) {
  85. c.unset('storeId');
  86. c.unset('storeName');
  87. cStoreCleaned++;
  88. changed = true;
  89. }
  90. if (c.get('districtId') !== undefined || c.get('districtName') !== undefined) {
  91. c.unset('districtId');
  92. c.unset('districtName');
  93. cDistrictCleaned++;
  94. changed = true;
  95. }
  96. if (changed) cToSave.push(c);
  97. }
  98. if (cToSave.length > 0) {
  99. await Parse.Object.saveAll(cToSave, { useMasterKey: true });
  100. }
  101. console.log(` Community: ${communities.length} 条, store 冗余 ${cStoreCleaned}, district 冗余 ${cDistrictCleaned}`);
  102. console.log('\n[Cleanup] 全部完成!');
  103. }
  104. main().catch((err) => {
  105. console.error('[Cleanup] 失败:', err);
  106. process.exit(1);
  107. });