aggregation.service.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import Parse from '../db/parse-client.js';
  2. export interface AggregateCountsResult {
  3. memberCountByRoom: Map<string, number>;
  4. todayMsgCountByRoom: Map<string, number>;
  5. totalMsgCountByRoom: Map<string, number>;
  6. groupCountByCommunity: Map<string, number>;
  7. }
  8. /** 按 roomId 字段分组计数 */
  9. function countByRoomId(rows: any[], roomIdField = 'roomId'): Map<string, number> {
  10. const map = new Map<string, number>();
  11. for (const r of rows) {
  12. const rid = typeof r.get === 'function' ? (r.get(roomIdField) as string) : (r[roomIdField] as string);
  13. if (rid) map.set(rid, (map.get(rid) || 0) + 1);
  14. }
  15. return map;
  16. }
  17. export async function fetchAggregateCounts(): Promise<AggregateCountsResult> {
  18. const todayStart = new Date();
  19. todayStart.setHours(0, 0, 0, 0);
  20. const [memberCounts, todayMsgCounts, totalMsgCounts, groupCounts] = await Promise.all([
  21. // 1. 活跃成员数 — select 只取 roomId
  22. (async () => {
  23. const q = new Parse.Query('GroupMember');
  24. q.equalTo('status', 'active');
  25. q.select('roomId');
  26. q.limit(100000);
  27. const rows = await q.find({ useMasterKey: true });
  28. return countByRoomId(rows);
  29. })(),
  30. // 2. 今日消息数 — select 只取 roomId
  31. (async () => {
  32. const q = new Parse.Query('Message');
  33. q.containedIn('msgType', [0, 2]);
  34. q.notEqualTo('content', '');
  35. q.greaterThanOrEqualTo('timestamp', todayStart);
  36. q.select('roomId');
  37. q.limit(100000);
  38. const rows = await q.find({ useMasterKey: true });
  39. return countByRoomId(rows);
  40. })(),
  41. // 3. 总消息数 — select 只取 roomId
  42. (async () => {
  43. const q = new Parse.Query('Message');
  44. q.select('roomId');
  45. q.limit(200000);
  46. const rows = await q.find({ useMasterKey: true });
  47. return countByRoomId(rows);
  48. })(),
  49. // 4. 群数按小区 — select 只取 community 指针
  50. (async () => {
  51. const q = new Parse.Query('GroupChat');
  52. q.select('community');
  53. q.limit(5000);
  54. const rows = await q.find({ useMasterKey: true });
  55. const map = new Map<string, number>();
  56. for (const r of rows) {
  57. const community = r.get('community');
  58. const cid = community?.id || '_null';
  59. map.set(cid, (map.get(cid) || 0) + 1);
  60. }
  61. return map;
  62. })(),
  63. ]);
  64. return {
  65. memberCountByRoom: memberCounts,
  66. todayMsgCountByRoom: todayMsgCounts,
  67. totalMsgCountByRoom: totalMsgCounts,
  68. groupCountByCommunity: groupCounts,
  69. };
  70. }