@mac777/project-pinecone-models 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Event.d.ts CHANGED
@@ -4,7 +4,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
4
4
  createdAt: NativeDate;
5
5
  updatedAt: NativeDate;
6
6
  status: "approved" | "rejected" | "draft" | "pending_approval" | "published" | "live" | "ended" | "cancelled";
7
- visibility: "public" | "private" | "unlisted";
8
7
  hostId: mongoose.Types.ObjectId;
9
8
  title: string;
10
9
  categories: string[];
@@ -12,15 +11,14 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
12
11
  languages: string[];
13
12
  tickets: mongoose.Types.DocumentArray<{
14
13
  name: string;
15
- status: "active" | "sold_out" | "inactive";
16
14
  quantity: number;
17
15
  sold: number;
18
- remaining: number;
19
- visibility: "hidden" | "public" | "invite_only";
20
16
  reserved: number;
17
+ isActive: boolean;
18
+ isVisible: boolean;
19
+ wristbandColor: string;
21
20
  benefits: string[];
22
21
  tier: string;
23
- description?: string | null | undefined;
24
22
  price?: {
25
23
  amount: number;
26
24
  currency: string;
@@ -35,15 +33,14 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
35
33
  } | null | undefined;
36
34
  }, mongoose.Types.Subdocument<mongoose.mongo.BSON.ObjectId, any, {
37
35
  name: string;
38
- status: "active" | "sold_out" | "inactive";
39
36
  quantity: number;
40
37
  sold: number;
41
- remaining: number;
42
- visibility: "hidden" | "public" | "invite_only";
43
38
  reserved: number;
39
+ isActive: boolean;
40
+ isVisible: boolean;
41
+ wristbandColor: string;
44
42
  benefits: string[];
45
43
  tier: string;
46
- description?: string | null | undefined;
47
44
  price?: {
48
45
  amount: number;
49
46
  currency: string;
@@ -58,15 +55,14 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
58
55
  } | null | undefined;
59
56
  }> & {
60
57
  name: string;
61
- status: "active" | "sold_out" | "inactive";
62
58
  quantity: number;
63
59
  sold: number;
64
- remaining: number;
65
- visibility: "hidden" | "public" | "invite_only";
66
60
  reserved: number;
61
+ isActive: boolean;
62
+ isVisible: boolean;
63
+ wristbandColor: string;
67
64
  benefits: string[];
68
65
  tier: string;
69
- description?: string | null | undefined;
70
66
  price?: {
71
67
  amount: number;
72
68
  currency: string;
@@ -83,6 +79,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
83
79
  termsAccepted: boolean;
84
80
  legalPermissionAccepted: boolean;
85
81
  platformTermsAccepted: boolean;
82
+ visibility: "public" | "private" | "unlisted";
86
83
  history: mongoose.Types.DocumentArray<{
87
84
  timestamp: NativeDate;
88
85
  action?: string | null | undefined;
@@ -195,15 +192,20 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
195
192
  publishedAt?: NativeDate | null | undefined;
196
193
  metrics?: {
197
194
  views: number;
195
+ uniqueViews: number;
196
+ totalOrders: number;
198
197
  ticketsSold: number;
199
198
  revenue: number;
200
199
  checkIns: number;
200
+ uniqueViewers: string[];
201
201
  reviewCount: number;
202
+ conversionRate: number;
203
+ lastViewedAt?: NativeDate | null | undefined;
202
204
  averageRating?: number | null | undefined;
203
205
  } | null | undefined;
204
206
  pricing?: {
207
+ currency: string;
205
208
  platformFee: number;
206
- currency?: string | null | undefined;
207
209
  paymentProcessingFee?: number | null | undefined;
208
210
  } | null | undefined;
209
211
  payout?: {
@@ -244,6 +246,8 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
244
246
  isFlagged: boolean;
245
247
  suspendedUntil?: NativeDate | null | undefined;
246
248
  banReason?: string | null | undefined;
249
+ suspendedAt?: NativeDate | null | undefined;
250
+ suspensionReason?: string | null | undefined;
247
251
  } | null | undefined;
248
252
  seo?: {
249
253
  keywords: string[];
@@ -255,6 +259,8 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
255
259
  isFeatured: boolean;
256
260
  isPremium: boolean;
257
261
  badges: string[];
262
+ featuredPriority: number;
263
+ featuredAt?: NativeDate | null | undefined;
258
264
  } | null | undefined;
259
265
  submittedAt?: NativeDate | null | undefined;
260
266
  deletedAt?: NativeDate | null | undefined;
@@ -265,7 +271,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
265
271
  createdAt: NativeDate;
266
272
  updatedAt: NativeDate;
267
273
  status: "approved" | "rejected" | "draft" | "pending_approval" | "published" | "live" | "ended" | "cancelled";
268
- visibility: "public" | "private" | "unlisted";
269
274
  hostId: mongoose.Types.ObjectId;
270
275
  title: string;
271
276
  categories: string[];
@@ -273,15 +278,14 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
273
278
  languages: string[];
274
279
  tickets: mongoose.Types.DocumentArray<{
275
280
  name: string;
276
- status: "active" | "sold_out" | "inactive";
277
281
  quantity: number;
278
282
  sold: number;
279
- remaining: number;
280
- visibility: "hidden" | "public" | "invite_only";
281
283
  reserved: number;
284
+ isActive: boolean;
285
+ isVisible: boolean;
286
+ wristbandColor: string;
282
287
  benefits: string[];
283
288
  tier: string;
284
- description?: string | null | undefined;
285
289
  price?: {
286
290
  amount: number;
287
291
  currency: string;
@@ -296,15 +300,14 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
296
300
  } | null | undefined;
297
301
  }, mongoose.Types.Subdocument<mongoose.mongo.BSON.ObjectId, any, {
298
302
  name: string;
299
- status: "active" | "sold_out" | "inactive";
300
303
  quantity: number;
301
304
  sold: number;
302
- remaining: number;
303
- visibility: "hidden" | "public" | "invite_only";
304
305
  reserved: number;
306
+ isActive: boolean;
307
+ isVisible: boolean;
308
+ wristbandColor: string;
305
309
  benefits: string[];
306
310
  tier: string;
307
- description?: string | null | undefined;
308
311
  price?: {
309
312
  amount: number;
310
313
  currency: string;
@@ -319,15 +322,14 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
319
322
  } | null | undefined;
320
323
  }> & {
321
324
  name: string;
322
- status: "active" | "sold_out" | "inactive";
323
325
  quantity: number;
324
326
  sold: number;
325
- remaining: number;
326
- visibility: "hidden" | "public" | "invite_only";
327
327
  reserved: number;
328
+ isActive: boolean;
329
+ isVisible: boolean;
330
+ wristbandColor: string;
328
331
  benefits: string[];
329
332
  tier: string;
330
- description?: string | null | undefined;
331
333
  price?: {
332
334
  amount: number;
333
335
  currency: string;
@@ -344,6 +346,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
344
346
  termsAccepted: boolean;
345
347
  legalPermissionAccepted: boolean;
346
348
  platformTermsAccepted: boolean;
349
+ visibility: "public" | "private" | "unlisted";
347
350
  history: mongoose.Types.DocumentArray<{
348
351
  timestamp: NativeDate;
349
352
  action?: string | null | undefined;
@@ -456,15 +459,20 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
456
459
  publishedAt?: NativeDate | null | undefined;
457
460
  metrics?: {
458
461
  views: number;
462
+ uniqueViews: number;
463
+ totalOrders: number;
459
464
  ticketsSold: number;
460
465
  revenue: number;
461
466
  checkIns: number;
467
+ uniqueViewers: string[];
462
468
  reviewCount: number;
469
+ conversionRate: number;
470
+ lastViewedAt?: NativeDate | null | undefined;
463
471
  averageRating?: number | null | undefined;
464
472
  } | null | undefined;
465
473
  pricing?: {
474
+ currency: string;
466
475
  platformFee: number;
467
- currency?: string | null | undefined;
468
476
  paymentProcessingFee?: number | null | undefined;
469
477
  } | null | undefined;
470
478
  payout?: {
@@ -505,6 +513,8 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
505
513
  isFlagged: boolean;
506
514
  suspendedUntil?: NativeDate | null | undefined;
507
515
  banReason?: string | null | undefined;
516
+ suspendedAt?: NativeDate | null | undefined;
517
+ suspensionReason?: string | null | undefined;
508
518
  } | null | undefined;
509
519
  seo?: {
510
520
  keywords: string[];
@@ -516,6 +526,8 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
516
526
  isFeatured: boolean;
517
527
  isPremium: boolean;
518
528
  badges: string[];
529
+ featuredPriority: number;
530
+ featuredAt?: NativeDate | null | undefined;
519
531
  } | null | undefined;
520
532
  submittedAt?: NativeDate | null | undefined;
521
533
  deletedAt?: NativeDate | null | undefined;
@@ -526,7 +538,6 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
526
538
  createdAt: NativeDate;
527
539
  updatedAt: NativeDate;
528
540
  status: "approved" | "rejected" | "draft" | "pending_approval" | "published" | "live" | "ended" | "cancelled";
529
- visibility: "public" | "private" | "unlisted";
530
541
  hostId: mongoose.Types.ObjectId;
531
542
  title: string;
532
543
  categories: string[];
@@ -534,15 +545,14 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
534
545
  languages: string[];
535
546
  tickets: mongoose.Types.DocumentArray<{
536
547
  name: string;
537
- status: "active" | "sold_out" | "inactive";
538
548
  quantity: number;
539
549
  sold: number;
540
- remaining: number;
541
- visibility: "hidden" | "public" | "invite_only";
542
550
  reserved: number;
551
+ isActive: boolean;
552
+ isVisible: boolean;
553
+ wristbandColor: string;
543
554
  benefits: string[];
544
555
  tier: string;
545
- description?: string | null | undefined;
546
556
  price?: {
547
557
  amount: number;
548
558
  currency: string;
@@ -557,15 +567,14 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
557
567
  } | null | undefined;
558
568
  }, mongoose.Types.Subdocument<mongoose.mongo.BSON.ObjectId, any, {
559
569
  name: string;
560
- status: "active" | "sold_out" | "inactive";
561
570
  quantity: number;
562
571
  sold: number;
563
- remaining: number;
564
- visibility: "hidden" | "public" | "invite_only";
565
572
  reserved: number;
573
+ isActive: boolean;
574
+ isVisible: boolean;
575
+ wristbandColor: string;
566
576
  benefits: string[];
567
577
  tier: string;
568
- description?: string | null | undefined;
569
578
  price?: {
570
579
  amount: number;
571
580
  currency: string;
@@ -580,15 +589,14 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
580
589
  } | null | undefined;
581
590
  }> & {
582
591
  name: string;
583
- status: "active" | "sold_out" | "inactive";
584
592
  quantity: number;
585
593
  sold: number;
586
- remaining: number;
587
- visibility: "hidden" | "public" | "invite_only";
588
594
  reserved: number;
595
+ isActive: boolean;
596
+ isVisible: boolean;
597
+ wristbandColor: string;
589
598
  benefits: string[];
590
599
  tier: string;
591
- description?: string | null | undefined;
592
600
  price?: {
593
601
  amount: number;
594
602
  currency: string;
@@ -605,6 +613,7 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
605
613
  termsAccepted: boolean;
606
614
  legalPermissionAccepted: boolean;
607
615
  platformTermsAccepted: boolean;
616
+ visibility: "public" | "private" | "unlisted";
608
617
  history: mongoose.Types.DocumentArray<{
609
618
  timestamp: NativeDate;
610
619
  action?: string | null | undefined;
@@ -717,15 +726,20 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
717
726
  publishedAt?: NativeDate | null | undefined;
718
727
  metrics?: {
719
728
  views: number;
729
+ uniqueViews: number;
730
+ totalOrders: number;
720
731
  ticketsSold: number;
721
732
  revenue: number;
722
733
  checkIns: number;
734
+ uniqueViewers: string[];
723
735
  reviewCount: number;
736
+ conversionRate: number;
737
+ lastViewedAt?: NativeDate | null | undefined;
724
738
  averageRating?: number | null | undefined;
725
739
  } | null | undefined;
726
740
  pricing?: {
741
+ currency: string;
727
742
  platformFee: number;
728
- currency?: string | null | undefined;
729
743
  paymentProcessingFee?: number | null | undefined;
730
744
  } | null | undefined;
731
745
  payout?: {
@@ -766,6 +780,8 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
766
780
  isFlagged: boolean;
767
781
  suspendedUntil?: NativeDate | null | undefined;
768
782
  banReason?: string | null | undefined;
783
+ suspendedAt?: NativeDate | null | undefined;
784
+ suspensionReason?: string | null | undefined;
769
785
  } | null | undefined;
770
786
  seo?: {
771
787
  keywords: string[];
@@ -777,6 +793,8 @@ declare const eventSchema: mongoose.Schema<any, mongoose.Model<any, any, any, an
777
793
  isFeatured: boolean;
778
794
  isPremium: boolean;
779
795
  badges: string[];
796
+ featuredPriority: number;
797
+ featuredAt?: NativeDate | null | undefined;
780
798
  } | null | undefined;
781
799
  submittedAt?: NativeDate | null | undefined;
782
800
  deletedAt?: NativeDate | null | undefined;
package/dist/Event.js CHANGED
@@ -77,24 +77,22 @@ const salesWindowSchema = new mongoose_1.default.Schema({
77
77
  startDate: Date,
78
78
  endDate: Date,
79
79
  }, { _id: false });
80
- const limitsSchema = new mongoose_1.default.Schema({
81
- minPerOrder: { type: Number, default: 1 },
82
- maxPerOrder: { type: Number, default: 10 },
83
- }, { _id: false });
84
80
  const ticketSchema = new mongoose_1.default.Schema({
85
81
  name: { type: String, required: true },
86
- description: String,
87
82
  price: priceSchema,
88
83
  quantity: { type: Number, required: true },
89
84
  sold: { type: Number, default: 0 },
90
- remaining: { type: Number, default: function () { return this.quantity - this.sold; } },
91
- salesWindow: salesWindowSchema,
92
- limits: limitsSchema,
93
- visibility: { type: String, enum: ['public', 'hidden', 'invite_only'], default: 'public' },
94
85
  reserved: { type: Number, default: 0 },
95
- status: { type: String, enum: ['active', 'sold_out', 'inactive'], default: 'active' },
86
+ isActive: { type: Boolean, default: true },
87
+ isVisible: { type: Boolean, default: true },
88
+ wristbandColor: { type: String, default: '#000000' },
89
+ limits: {
90
+ minPerOrder: { type: Number, default: 1 },
91
+ maxPerOrder: { type: Number, default: 10 },
92
+ },
96
93
  benefits: [String],
97
- tier: { type: String, required: true, default: 'regular' },
94
+ tier: { type: String, default: 'regular' },
95
+ salesWindow: salesWindowSchema,
98
96
  });
99
97
  const scheduleSchema = new mongoose_1.default.Schema({
100
98
  startDate: { type: Date, required: true },
@@ -105,16 +103,25 @@ const scheduleSchema = new mongoose_1.default.Schema({
105
103
  }, { _id: false });
106
104
  const metricsSchema = new mongoose_1.default.Schema({
107
105
  views: { type: Number, default: 0 },
106
+ uniqueViews: { type: Number, default: 0 },
107
+ totalOrders: { type: Number, default: 0 },
108
108
  ticketsSold: { type: Number, default: 0 },
109
109
  revenue: { type: Number, default: 0 },
110
110
  checkIns: { type: Number, default: 0 },
111
+ uniqueViewers: [String],
112
+ lastViewedAt: Date, // for trending calculation
113
+ // --- For Review ---
111
114
  averageRating: Number,
112
115
  reviewCount: { type: Number, default: 0 },
116
+ conversionRate: { type: Number, default: 0 }, // (ticketsSold / views) * 100
113
117
  }, { _id: false });
114
118
  const pricingSchema = new mongoose_1.default.Schema({
115
119
  platformFee: { type: Number, default: 5 },
116
120
  paymentProcessingFee: Number,
117
- currency: String,
121
+ currency: {
122
+ type: String,
123
+ default: 'BDT'
124
+ },
118
125
  }, { _id: false });
119
126
  const payoutSchema = new mongoose_1.default.Schema({
120
127
  status: { type: String, enum: ['pending', 'scheduled', 'completed'] },
@@ -144,6 +151,8 @@ const moderationSchema = new mongoose_1.default.Schema({
144
151
  flags: [flagSchema],
145
152
  suspendedUntil: Date,
146
153
  banReason: String,
154
+ suspendedAt: Date,
155
+ suspensionReason: String,
147
156
  }, { _id: false });
148
157
  const seoSchema = new mongoose_1.default.Schema({
149
158
  metaTitle: String,
@@ -155,6 +164,8 @@ const featuresSchema = new mongoose_1.default.Schema({
155
164
  isFeatured: { type: Boolean, default: false },
156
165
  isPremium: { type: Boolean, default: false },
157
166
  badges: [String],
167
+ featuredAt: Date, // timestamp when featured
168
+ featuredPriority: { type: Number, default: 0 }, // for ordering featured events
158
169
  }, { _id: false });
159
170
  const historySchema = new mongoose_1.default.Schema({
160
171
  action: String,
@@ -221,6 +232,17 @@ eventSchema.index({ hostId: 1 });
221
232
  eventSchema.index({ 'schedule.startDate': 1 });
222
233
  eventSchema.index({ type: 1 });
223
234
  eventSchema.index({ categories: 1 });
235
+ // New compound indexes for optimized queries
236
+ // For trending events (recent views + high sales)
237
+ eventSchema.index({ 'metrics.lastViewedAt': -1, 'metrics.ticketsSold': -1 });
238
+ // For featured events
239
+ eventSchema.index({ 'features.isFeatured': 1, 'features.featuredPriority': -1 });
240
+ // For filtering by status + visibility + date
241
+ eventSchema.index({ status: 1, visibility: 1, 'schedule.startDate': 1 });
242
+ // For location-based queries with status
243
+ eventSchema.index({ 'venue.address.city': 1, status: 1 });
244
+ // For host's events with status filter
245
+ eventSchema.index({ hostId: 1, status: 1, updatedAt: -1 });
224
246
  // Validation: sum(tickets.quantity) <= venue.capacity
225
247
  eventSchema.pre('save', function (next) {
226
248
  if (this.tickets && this.tickets.length > 0 && this.venue) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mac777/project-pinecone-models",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
package/src/Event.ts CHANGED
@@ -82,25 +82,22 @@ const salesWindowSchema = new mongoose.Schema({
82
82
  endDate: Date,
83
83
  }, { _id: false });
84
84
 
85
- const limitsSchema = new mongoose.Schema({
86
- minPerOrder: { type: Number, default: 1 },
87
- maxPerOrder: { type: Number, default: 10 },
88
- }, { _id: false });
89
-
90
85
  const ticketSchema = new mongoose.Schema({
91
86
  name: { type: String, required: true },
92
- description: String,
93
87
  price: priceSchema,
94
88
  quantity: { type: Number, required: true },
95
89
  sold: { type: Number, default: 0 },
96
- remaining: { type: Number, default: function(this: any) { return this.quantity - this.sold; } },
97
- salesWindow: salesWindowSchema,
98
- limits: limitsSchema,
99
- visibility: { type: String, enum: ['public', 'hidden', 'invite_only'], default: 'public' },
100
90
  reserved: { type: Number, default: 0 },
101
- status: { type: String, enum: ['active', 'sold_out', 'inactive'], default: 'active' },
91
+ isActive: { type: Boolean, default: true },
92
+ isVisible: { type: Boolean, default: true },
93
+ wristbandColor: { type: String, default: '#000000' },
94
+ limits: {
95
+ minPerOrder: { type: Number, default: 1 },
96
+ maxPerOrder: { type: Number, default: 10 },
97
+ },
102
98
  benefits: [String],
103
- tier: { type: String, required: true, default: 'regular' },
99
+ tier: { type: String, default: 'regular' },
100
+ salesWindow: salesWindowSchema,
104
101
  });
105
102
 
106
103
  const scheduleSchema = new mongoose.Schema({
@@ -113,17 +110,27 @@ const scheduleSchema = new mongoose.Schema({
113
110
 
114
111
  const metricsSchema = new mongoose.Schema({
115
112
  views: { type: Number, default: 0 },
113
+ uniqueViews: { type: Number, default: 0 },
114
+ totalOrders: { type: Number, default: 0 },
116
115
  ticketsSold: { type: Number, default: 0 },
117
116
  revenue: { type: Number, default: 0 },
118
117
  checkIns: { type: Number, default: 0 },
118
+ uniqueViewers: [String],
119
+ lastViewedAt: Date, // for trending calculation
120
+
121
+ // --- For Review ---
119
122
  averageRating: Number,
120
123
  reviewCount: { type: Number, default: 0 },
124
+ conversionRate: { type: Number, default: 0 }, // (ticketsSold / views) * 100
121
125
  }, { _id: false });
122
126
 
123
127
  const pricingSchema = new mongoose.Schema({
124
128
  platformFee: { type: Number, default: 5 },
125
129
  paymentProcessingFee: Number,
126
- currency: String,
130
+ currency: {
131
+ type: String,
132
+ default: 'BDT'
133
+ },
127
134
  }, { _id: false });
128
135
 
129
136
  const payoutSchema = new mongoose.Schema({
@@ -158,6 +165,8 @@ const moderationSchema = new mongoose.Schema({
158
165
  flags: [flagSchema],
159
166
  suspendedUntil: Date,
160
167
  banReason: String,
168
+ suspendedAt: Date,
169
+ suspensionReason: String,
161
170
  }, { _id: false });
162
171
 
163
172
  const seoSchema = new mongoose.Schema({
@@ -171,6 +180,8 @@ const featuresSchema = new mongoose.Schema({
171
180
  isFeatured: { type: Boolean, default: false },
172
181
  isPremium: { type: Boolean, default: false },
173
182
  badges: [String],
183
+ featuredAt: Date, // timestamp when featured
184
+ featuredPriority: { type: Number, default: 0 }, // for ordering featured events
174
185
  }, { _id: false });
175
186
 
176
187
  const historySchema = new mongoose.Schema({
@@ -254,6 +265,22 @@ eventSchema.index({ 'schedule.startDate': 1 });
254
265
  eventSchema.index({ type: 1 });
255
266
  eventSchema.index({ categories: 1 });
256
267
 
268
+ // New compound indexes for optimized queries
269
+ // For trending events (recent views + high sales)
270
+ eventSchema.index({ 'metrics.lastViewedAt': -1, 'metrics.ticketsSold': -1 });
271
+
272
+ // For featured events
273
+ eventSchema.index({ 'features.isFeatured': 1, 'features.featuredPriority': -1 });
274
+
275
+ // For filtering by status + visibility + date
276
+ eventSchema.index({ status: 1, visibility: 1, 'schedule.startDate': 1 });
277
+
278
+ // For location-based queries with status
279
+ eventSchema.index({ 'venue.address.city': 1, status: 1 });
280
+
281
+ // For host's events with status filter
282
+ eventSchema.index({ hostId: 1, status: 1, updatedAt: -1 });
283
+
257
284
  // Validation: sum(tickets.quantity) <= venue.capacity
258
285
  eventSchema.pre('save', function(next) {
259
286
  if (this.tickets && this.tickets.length > 0 && this.venue) {