Przeglądaj źródła

messageRecord增加索引

guoziyun 9 miesięcy temu
rodzic
commit
a6ceb818f5

+ 2 - 2
oms/dist/services/cron-jobs/notify/local-timezone-notify.js

@@ -134,8 +134,8 @@ async function run() {
     try {
         const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
         const activeUsers = await userModel_1.User.find({
-            // lastActiveAt: { $gte: sevenDaysAgo },
-            $or: [{ lastActiveAt: { $gte: sevenDaysAgo } }, { lastActiveAt: { $in: [null, "", undefined] } }],
+            lastActiveAt: { $gte: sevenDaysAgo },
+            // $or: [{ lastActiveAt: { $gte: sevenDaysAgo } }, { lastActiveAt: { $in: [null, "", undefined] } }],
             fmToken: { $nin: [null, ""] },
             versionCode: { $gte: 347 },
         })

+ 1 - 5
oms/dist/services/ingestor-service.js

@@ -332,11 +332,7 @@ async function processMessage(msg) {
         // --- 3. Prepare User Data for MongoDB Batch Update ---
         // userSetData will contain fields to be updated using $set for both new and existing documents.
         // 'project' is now excluded here as it will be handled by $setOnInsert only.
-        // const userSetData: Partial<IUser> = { lastActiveAt: lastActiveAtDateObj };
-        const userSetData = {};
-        if (eventType !== "message_receive") {
-            userSetData.lastActiveAt = lastActiveAtDateObj;
-        }
+        const userSetData = { lastActiveAt: lastActiveAtDateObj };
         // SetOnInsert fields will only apply when a new document is created
         const setOnInsertFields = {
             uid: uid,

+ 46 - 1
oms/dist/src/models/messageRecordModel.js

@@ -122,5 +122,50 @@ const messageRecordSchema = new mongoose_1.Schema({
     timestamps: true, // Automatically adds createdAt and updatedAt
 });
 // Added compound index for common queries by user and status
-messageRecordSchema.index({ uid: 1, status: 1 });
+messageRecordSchema.index({ uid: 1, status: 1 }); // 按用户+状态查询
+// --------------------------
+// 2. 新增复合索引(核心优化)
+// --------------------------
+/**
+ * 场景1:日期范围 + 策略筛选(高频)
+ * 覆盖接口:getOverallStatistics、getDailySentTrends、getStatisticsByStrategy、getDailyTrendsByStrategy
+ */
+messageRecordSchema.index({ createdAt: 1, strategyName: 1 });
+/**
+ * 场景2:日期范围 + 模板筛选(高频)
+ * 覆盖接口:getStatisticsByTemplate、getDailyTrendsByTemplate
+ */
+messageRecordSchema.index({ createdAt: 1, templateName: 1 });
+/**
+ * 场景3:日期范围 + 国家代码筛选(高频)
+ * 覆盖接口:getStatisticsByCc、getDailyTrendsByCc
+ */
+messageRecordSchema.index({ createdAt: 1, cc: 1 });
+/**
+ * 场景4:日期范围 + 图片筛选(高频)
+ * 覆盖接口:getStatisticsByImage、getDailyTrendsByImage
+ */
+messageRecordSchema.index({ createdAt: 1, image: 1 });
+/**
+ * 场景5:日期范围 + 活动名称筛选(中频)
+ * 覆盖接口:getStatisticsByActivity
+ */
+messageRecordSchema.index({ createdAt: 1, activityName: 1 });
+/**
+ * 场景6:日期范围 + 状态筛选(中频,用于状态维度统计)
+ * 覆盖接口:getPaginatedRecords(日期+状态筛选)、部分聚合统计
+ */
+messageRecordSchema.index({ createdAt: 1, status: 1 });
+// --------------------------
+// 3. 可选:覆盖索引(针对极高频统计查询,进一步减少IO)
+// --------------------------
+/**
+ * 场景:每日趋势统计(getDailySentTrends),聚合需用到 createdAt/status/inforeground/uid
+ * 覆盖索引包含所有聚合所需字段,无需查询原始文档
+ */
+messageRecordSchema.index({ createdAt: 1, strategyName: 1 }, {
+    includeFields: { status: 1, inforeground: 1, uid: 1 }, // MongoDB 原生支持的语法
+    name: "idx_createdAt_strategy_include_agg",
+} // 类型断言,避免 TypeScript 报错
+);
 exports.MessageRecord = (0, mongoose_1.model)("MessageRecord", messageRecordSchema);

+ 55 - 1
oms/src/models/messageRecordModel.ts

@@ -159,6 +159,60 @@ const messageRecordSchema = new Schema<IMessageRecord>(
 );
 
 // Added compound index for common queries by user and status
-messageRecordSchema.index({ uid: 1, status: 1 });
+messageRecordSchema.index({ uid: 1, status: 1 }); // 按用户+状态查询
+
+// --------------------------
+// 2. 新增复合索引(核心优化)
+// --------------------------
+/**
+ * 场景1:日期范围 + 策略筛选(高频)
+ * 覆盖接口:getOverallStatistics、getDailySentTrends、getStatisticsByStrategy、getDailyTrendsByStrategy
+ */
+messageRecordSchema.index({ createdAt: 1, strategyName: 1 });
+
+/**
+ * 场景2:日期范围 + 模板筛选(高频)
+ * 覆盖接口:getStatisticsByTemplate、getDailyTrendsByTemplate
+ */
+messageRecordSchema.index({ createdAt: 1, templateName: 1 });
+
+/**
+ * 场景3:日期范围 + 国家代码筛选(高频)
+ * 覆盖接口:getStatisticsByCc、getDailyTrendsByCc
+ */
+messageRecordSchema.index({ createdAt: 1, cc: 1 });
+
+/**
+ * 场景4:日期范围 + 图片筛选(高频)
+ * 覆盖接口:getStatisticsByImage、getDailyTrendsByImage
+ */
+messageRecordSchema.index({ createdAt: 1, image: 1 });
+
+/**
+ * 场景5:日期范围 + 活动名称筛选(中频)
+ * 覆盖接口:getStatisticsByActivity
+ */
+messageRecordSchema.index({ createdAt: 1, activityName: 1 });
+
+/**
+ * 场景6:日期范围 + 状态筛选(中频,用于状态维度统计)
+ * 覆盖接口:getPaginatedRecords(日期+状态筛选)、部分聚合统计
+ */
+messageRecordSchema.index({ createdAt: 1, status: 1 });
+
+// --------------------------
+// 3. 可选:覆盖索引(针对极高频统计查询,进一步减少IO)
+// --------------------------
+/**
+ * 场景:每日趋势统计(getDailySentTrends),聚合需用到 createdAt/status/inforeground/uid
+ * 覆盖索引包含所有聚合所需字段,无需查询原始文档
+ */
+messageRecordSchema.index(
+  { createdAt: 1, strategyName: 1 },
+  {
+    includeFields: { status: 1, inforeground: 1, uid: 1 }, // MongoDB 原生支持的语法
+    name: "idx_createdAt_strategy_include_agg",
+  } as any // 类型断言,避免 TypeScript 报错
+);
 
 export const MessageRecord = model<IMessageRecord>("MessageRecord", messageRecordSchema);