database-connector 2.0.4 → 2.1.0
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/CHANGELOG.md +182 -1
- package/models/Bill.js +9 -0
- package/models/Cart.js +4 -0
- package/models/Notification.js +7 -0
- package/models/Offer.js +9 -0
- package/models/Order.js +12 -0
- package/models/Payment.js +8 -0
- package/models/Product.js +14 -0
- package/models/ResetPassword.js +5 -0
- package/models/Sale.js +7 -0
- package/models/Store.js +8 -1
- package/models/Subscription.js +10 -0
- package/models/User.js +6 -0
- package/models/UserAction.js +7 -0
- package/models/View.js +8 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,187 @@
|
|
|
1
1
|
# Changelog - Database Connector Models Refactoring
|
|
2
2
|
|
|
3
|
-
## 2025-12-08
|
|
3
|
+
## 2025-12-08 - Database Indexes Optimization
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
#### Database Indexes for Performance Optimization
|
|
8
|
+
|
|
9
|
+
After comprehensive analysis of model usage across all microservices (AuthService, CartService, CategoryService, NotificationService, OfferService, OrderService, ProductService, SalesAnalyticsService, SearchExplorationService, StoreService, SubscriptionService, and UserService), the following database indexes have been added to optimize query performance:
|
|
10
|
+
|
|
11
|
+
**1. User Model** (`User.js`)
|
|
12
|
+
- **Indexes Added:**
|
|
13
|
+
- `email` (sparse): For login authentication by email in AuthService
|
|
14
|
+
- `phone` (sparse): For login authentication by phone in AuthService
|
|
15
|
+
- `role`: For filtering users by role (admin, seller, manager, etc.)
|
|
16
|
+
- `storeSubs`: For finding users subscribed to specific stores (ProductService notifications)
|
|
17
|
+
- **Justification:** AuthService performs frequent lookups by email, phone, and username. The sparse indexes on email and phone allow for null values while optimizing lookups. Role-based queries are common in user management.
|
|
18
|
+
|
|
19
|
+
**2. Cart Model** (`Cart.js`)
|
|
20
|
+
- **Indexes Added:**
|
|
21
|
+
- `userId` (unique): Already existed, ensures one cart per user
|
|
22
|
+
- `items.productId`: For querying carts containing specific products
|
|
23
|
+
- **Justification:** CartService frequently queries carts by userId and needs to find items by productId for cart operations.
|
|
24
|
+
|
|
25
|
+
**3. Product Model** (`Product.js`)
|
|
26
|
+
- **Indexes Added:**
|
|
27
|
+
- `storeId, deleted` (compound): For fetching active products by store
|
|
28
|
+
- `sellerId`: For seller-specific product queries in SellerRecommendationEngine
|
|
29
|
+
- `categoryId`: For category-based filtering
|
|
30
|
+
- `storeCategoryId`: For store category navigation
|
|
31
|
+
- `deleted`: For filtering deleted products
|
|
32
|
+
- `numberOfSales` (descending): For top-selling products
|
|
33
|
+
- `numberOfViews` (descending): For most-viewed products
|
|
34
|
+
- `averageRating` (descending): For highest-rated products sorting
|
|
35
|
+
- `createdAt` (descending): For newest products first
|
|
36
|
+
- `price`: For price range filtering
|
|
37
|
+
- `tags`: For tag-based search
|
|
38
|
+
- `variants._id`: For variant-specific queries in OrderService
|
|
39
|
+
- **Justification:** ProductService has extensive query patterns including filtering by store, category, deletion status, and sorting by sales/views/ratings. SearchExplorationService uses price and tag filters. The compound index on storeId+deleted optimizes the most common query pattern.
|
|
40
|
+
|
|
41
|
+
**4. Store Model** (`Store.js`)
|
|
42
|
+
- **Indexes Added:**
|
|
43
|
+
- `location` (2dsphere): For geospatial proximity queries
|
|
44
|
+
- `sellerId`: For finding stores by seller
|
|
45
|
+
- `address.city`: For city-based store searches
|
|
46
|
+
- `isActive`: For filtering active stores
|
|
47
|
+
- `activated`: For filtering activated stores
|
|
48
|
+
- `storeCategorieIds`: For category-based store filtering
|
|
49
|
+
- `ratingSum, ratingCount` (compound descending): For sorting stores by rating
|
|
50
|
+
- **Justification:** StoreService performs geospatial queries for nearby stores, city-based searches, and seller-specific queries. The 2dsphere index enables efficient location-based searches. Rating-based sorting is common in store listings.
|
|
51
|
+
|
|
52
|
+
**5. Order Model** (`Order.js`)
|
|
53
|
+
- **Indexes Added:**
|
|
54
|
+
- `clientId`: For user order history
|
|
55
|
+
- `storeId`: For store order management
|
|
56
|
+
- `status`: For filtering orders by status
|
|
57
|
+
- `paymentId`: For payment-related order lookups
|
|
58
|
+
- `shippingStatus`: For shipping status filtering
|
|
59
|
+
- `paymentStatus`: For payment status filtering
|
|
60
|
+
- `createdAt` (descending): For recent orders first
|
|
61
|
+
- `clientId, storeId` (compound): For user orders at specific store
|
|
62
|
+
- `storeId, status` (compound): For store orders by status
|
|
63
|
+
- **Justification:** OrderService queries orders by client, store, various statuses, and payment ID. GDPR service exports user order data. Compound indexes optimize common filtering combinations.
|
|
64
|
+
|
|
65
|
+
**6. Notification Model** (`Notification.js`)
|
|
66
|
+
- **Indexes Added:**
|
|
67
|
+
- `owner_id, createdAt` (compound descending): For user notifications sorted by date
|
|
68
|
+
- `owner_id, seend` (compound): For filtering read/unread notifications
|
|
69
|
+
- `owner_id, seendInList` (compound): For list view status
|
|
70
|
+
- `type`: For filtering by notification type
|
|
71
|
+
- `sub_type`: For filtering by notification sub-type
|
|
72
|
+
- **Justification:** NotificationService queries notifications by owner with sorting by date and filtering by read status. Compound indexes optimize these common query patterns.
|
|
73
|
+
|
|
74
|
+
**7. Sale Model** (`Sale.js`)
|
|
75
|
+
- **Indexes Added:**
|
|
76
|
+
- `sellerId, date` (compound descending): For seller sales analytics
|
|
77
|
+
- `storeId, date` (compound descending): For store sales analytics
|
|
78
|
+
- `productId, date` (compound descending): For product sales analytics
|
|
79
|
+
- `date` (descending): For time-based analytics
|
|
80
|
+
- `region`: For regional sales analysis
|
|
81
|
+
- **Justification:** SalesAnalyticsService aggregates sales by seller, store, product, and time periods. Compound indexes with date optimize time-series analytics queries.
|
|
82
|
+
|
|
83
|
+
**8. View Model** (`View.js`)
|
|
84
|
+
- **Indexes Added:**
|
|
85
|
+
- `sellerId, date` (compound descending): For seller view analytics
|
|
86
|
+
- `storeId, date` (compound descending): For store view analytics
|
|
87
|
+
- `productId, date` (compound descending): For product view analytics
|
|
88
|
+
- `clientId, date` (compound descending): For user browsing history
|
|
89
|
+
- `date` (descending): For time-based view analytics
|
|
90
|
+
- `region`: For regional view analysis
|
|
91
|
+
- **Justification:** SalesAnalyticsService aggregates views by seller, store, product, client, and time periods. These indexes support the analytics aggregation pipelines.
|
|
92
|
+
|
|
93
|
+
**9. Payment Model** (`Payment.js`)
|
|
94
|
+
- **Indexes Added:**
|
|
95
|
+
- `userId, createdAt` (compound descending): For user payment history
|
|
96
|
+
- `sellerId, createdAt` (compound descending): For seller payment tracking
|
|
97
|
+
- `paymentStatus`: For filtering by payment status
|
|
98
|
+
- `token`: For payment token lookups
|
|
99
|
+
- `gateway`: For filtering by payment gateway
|
|
100
|
+
- `paymentDate` (descending): For date-based payment queries
|
|
101
|
+
- **Justification:** Payment tracking requires efficient queries by user, seller, status, and token. Date-based sorting is common in payment history.
|
|
102
|
+
|
|
103
|
+
**10. Bill Model** (`Bill.js`)
|
|
104
|
+
- **Indexes Added:**
|
|
105
|
+
- `userId, createdAt` (compound descending): For user billing history
|
|
106
|
+
- `storeId, createdAt` (compound descending): For store billing records
|
|
107
|
+
- `paymentStatus`: For payment status filtering
|
|
108
|
+
- `shippingStatus`: For shipping status filtering
|
|
109
|
+
- `refundStatus`: For refund status filtering
|
|
110
|
+
- `paymentId`: For payment-bill relationship
|
|
111
|
+
- `userId, storeId` (compound): For user bills at specific store
|
|
112
|
+
- **Justification:** Bill management requires queries by user, store, various statuses, and payment associations. Compound indexes optimize common query patterns.
|
|
113
|
+
|
|
114
|
+
**11. Offer Model** (`Offer.js`)
|
|
115
|
+
- **Indexes Added:**
|
|
116
|
+
- `sellerId, offerStatus` (compound): For seller offers by status
|
|
117
|
+
- `storeId, offerStatus` (compound): For store offers by status
|
|
118
|
+
- `productId`: For product-specific offers
|
|
119
|
+
- `offerStatus`: For filtering active/expired offers
|
|
120
|
+
- `offerExpiration`: For expiration-based queries
|
|
121
|
+
- `createdAt` (descending): For newest offers first
|
|
122
|
+
- `offerDeleted`: For filtering deleted offers
|
|
123
|
+
- **Justification:** OfferService queries offers by seller, store, product, and status. Compound indexes optimize seller and store offer listings with status filtering.
|
|
124
|
+
|
|
125
|
+
**12. Subscription Model** (`Subscription.js`)
|
|
126
|
+
- **Indexes Added:**
|
|
127
|
+
- `storeId`: For store subscription lookup
|
|
128
|
+
- `status`: For filtering by subscription status
|
|
129
|
+
- `endDate`: For expiration checks
|
|
130
|
+
- `startDate`: For activation tracking
|
|
131
|
+
- `planId`: For plan-based queries
|
|
132
|
+
- `paymentManagerId`: For payment manager tracking
|
|
133
|
+
- `storeId, status` (compound): For store subscription status
|
|
134
|
+
- `status, endDate` (compound): For active subscription expiration monitoring
|
|
135
|
+
- **Justification:** SubscriptionService queries subscriptions by store, status, and expiration dates. Compound indexes optimize active subscription monitoring and store subscription management.
|
|
136
|
+
|
|
137
|
+
**13. UserAction Model** (`UserAction.js`)
|
|
138
|
+
- **Indexes Added:**
|
|
139
|
+
- `userId, timestamp` (compound descending): For user activity timeline
|
|
140
|
+
- `type`: For filtering by action type
|
|
141
|
+
- `sessionId`: For session-based analytics
|
|
142
|
+
- `deviceId`: For device-based tracking
|
|
143
|
+
- `timestamp` (descending): For recent activity queries
|
|
144
|
+
- **Justification:** UserService tracks user actions for analytics and GDPR data export. Compound index on userId+timestamp optimizes user activity timeline queries.
|
|
145
|
+
|
|
146
|
+
**14. ResetPassword Model** (`ResetPassword.js`)
|
|
147
|
+
- **Indexes Added:**
|
|
148
|
+
- `userId`: For user password reset lookups
|
|
149
|
+
- `token`: For token verification
|
|
150
|
+
- `createAt` (TTL index, expires: 3600s): Automatic cleanup of expired tokens
|
|
151
|
+
- **Justification:** AuthService looks up reset tokens by userId and token. TTL index automatically removes expired reset tokens after 1 hour, maintaining database hygiene.
|
|
152
|
+
|
|
153
|
+
### Performance Impact
|
|
154
|
+
|
|
155
|
+
**Query Performance Improvements:**
|
|
156
|
+
- **Single-field indexes:** Reduce query time from O(n) to O(log n) for exact matches
|
|
157
|
+
- **Compound indexes:** Optimize queries filtering by multiple fields simultaneously
|
|
158
|
+
- **Geospatial index (Store):** Enable efficient proximity searches for nearby stores
|
|
159
|
+
- **Descending indexes:** Optimize sorted queries (newest first, highest rated, etc.)
|
|
160
|
+
- **Sparse indexes (User email/phone):** Allow null values while optimizing lookups
|
|
161
|
+
- **TTL index (ResetPassword):** Automatic cleanup reduces manual maintenance
|
|
162
|
+
|
|
163
|
+
**Index Strategy:**
|
|
164
|
+
- Compound indexes placed on most frequent query combinations
|
|
165
|
+
- Sort direction matches common query patterns (descending for dates, ratings, views)
|
|
166
|
+
- Sparse indexes used for optional fields to reduce index size
|
|
167
|
+
- Array field indexes support multi-valued queries
|
|
168
|
+
|
|
169
|
+
### Maintenance Notes
|
|
170
|
+
|
|
171
|
+
**Index Monitoring:**
|
|
172
|
+
- Monitor index usage with MongoDB's `db.collection.aggregate([{$indexStats:{}}])`
|
|
173
|
+
- Review slow query logs to identify missing indexes
|
|
174
|
+
- Update indexes as query patterns evolve
|
|
175
|
+
|
|
176
|
+
**Index Size Considerations:**
|
|
177
|
+
- Each index consumes disk space and memory
|
|
178
|
+
- Indexes slow down write operations slightly
|
|
179
|
+
- Compound indexes can serve queries on their prefix fields
|
|
180
|
+
- Consider removing unused indexes based on monitoring data
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 2025-12-08 - Initial Refactoring
|
|
4
185
|
|
|
5
186
|
### Added
|
|
6
187
|
|
package/models/Bill.js
CHANGED
|
@@ -173,6 +173,15 @@ const BillSchema = new mongoose.Schema(
|
|
|
173
173
|
}
|
|
174
174
|
);
|
|
175
175
|
|
|
176
|
+
// Indexes for performance optimization
|
|
177
|
+
BillSchema.index({ userId: 1, createdAt: -1 });
|
|
178
|
+
BillSchema.index({ storeId: 1, createdAt: -1 });
|
|
179
|
+
BillSchema.index({ paymentStatus: 1 });
|
|
180
|
+
BillSchema.index({ shippingStatus: 1 });
|
|
181
|
+
BillSchema.index({ refundStatus: 1 });
|
|
182
|
+
BillSchema.index({ paymentId: 1 });
|
|
183
|
+
BillSchema.index({ userId: 1, storeId: 1 });
|
|
184
|
+
|
|
176
185
|
// Virtual: calculate amount that needs to be paid
|
|
177
186
|
BillSchema.virtual('needToBePay').get(function () {
|
|
178
187
|
if (this.paymentStatus === 'pending') {
|
package/models/Cart.js
CHANGED
|
@@ -105,4 +105,8 @@ cartSchema.virtual('totalPriceForAllProducts').get(function () {
|
|
|
105
105
|
}, 0);
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
+
// Indexes for performance optimization
|
|
109
|
+
cartSchema.index({ userId: 1 }, { unique: true });
|
|
110
|
+
cartSchema.index({ 'items.productId': 1 });
|
|
111
|
+
|
|
108
112
|
module.exports = model('Cart', cartSchema);
|
package/models/Notification.js
CHANGED
|
@@ -91,4 +91,11 @@ const NotificationSchema = new mongoose.Schema(
|
|
|
91
91
|
{ timestamps: true }
|
|
92
92
|
);
|
|
93
93
|
|
|
94
|
+
// Indexes for performance optimization
|
|
95
|
+
NotificationSchema.index({ owner_id: 1, createdAt: -1 });
|
|
96
|
+
NotificationSchema.index({ owner_id: 1, seend: 1 });
|
|
97
|
+
NotificationSchema.index({ owner_id: 1, seendInList: 1 });
|
|
98
|
+
NotificationSchema.index({ type: 1 });
|
|
99
|
+
NotificationSchema.index({ sub_type: 1 });
|
|
100
|
+
|
|
94
101
|
module.exports = mongoose.model('Notification', NotificationSchema);
|
package/models/Offer.js
CHANGED
|
@@ -146,4 +146,13 @@ OfferSchema.virtual('active').get(function () {
|
|
|
146
146
|
return this.offerExpiration > Date.now();
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
+
// Indexes for performance optimization
|
|
150
|
+
OfferSchema.index({ sellerId: 1, offerStatus: 1 });
|
|
151
|
+
OfferSchema.index({ storeId: 1, offerStatus: 1 });
|
|
152
|
+
OfferSchema.index({ productId: 1 });
|
|
153
|
+
OfferSchema.index({ offerStatus: 1 });
|
|
154
|
+
OfferSchema.index({ offerExpiration: 1 });
|
|
155
|
+
OfferSchema.index({ createdAt: -1 });
|
|
156
|
+
OfferSchema.index({ offerDeleted: 1 });
|
|
157
|
+
|
|
149
158
|
module.exports = mongoose.model('Offer', OfferSchema);
|
package/models/Order.js
CHANGED
|
@@ -314,4 +314,16 @@ orderSchema.post('save', async function (doc) {
|
|
|
314
314
|
console.error('Error creating sale records:', error);
|
|
315
315
|
}
|
|
316
316
|
});
|
|
317
|
+
|
|
318
|
+
// Indexes for performance optimization
|
|
319
|
+
orderSchema.index({ clientId: 1 });
|
|
320
|
+
orderSchema.index({ storeId: 1 });
|
|
321
|
+
orderSchema.index({ status: 1 });
|
|
322
|
+
orderSchema.index({ paymentId: 1 });
|
|
323
|
+
orderSchema.index({ shippingStatus: 1 });
|
|
324
|
+
orderSchema.index({ paymentStatus: 1 });
|
|
325
|
+
orderSchema.index({ createdAt: -1 });
|
|
326
|
+
orderSchema.index({ clientId: 1, storeId: 1 });
|
|
327
|
+
orderSchema.index({ storeId: 1, status: 1 });
|
|
328
|
+
|
|
317
329
|
module.exports = mongoose.model('Order', orderSchema);
|
package/models/Payment.js
CHANGED
|
@@ -191,4 +191,12 @@ const paymentSchema = new mongoose.Schema(
|
|
|
191
191
|
{ timestamps: true }
|
|
192
192
|
);
|
|
193
193
|
|
|
194
|
+
// Indexes for performance optimization
|
|
195
|
+
paymentSchema.index({ userId: 1, createdAt: -1 });
|
|
196
|
+
paymentSchema.index({ sellerId: 1, createdAt: -1 });
|
|
197
|
+
paymentSchema.index({ paymentStatus: 1 });
|
|
198
|
+
paymentSchema.index({ token: 1 });
|
|
199
|
+
paymentSchema.index({ gateway: 1 });
|
|
200
|
+
paymentSchema.index({ paymentDate: -1 });
|
|
201
|
+
|
|
194
202
|
module.exports = mongoose.model('Payment', paymentSchema);
|
package/models/Product.js
CHANGED
|
@@ -295,4 +295,18 @@ productSchema.virtual('variantImages').get(function () {
|
|
|
295
295
|
}
|
|
296
296
|
});
|
|
297
297
|
|
|
298
|
+
// Indexes for performance optimization
|
|
299
|
+
productSchema.index({ storeId: 1, deleted: 1 });
|
|
300
|
+
productSchema.index({ sellerId: 1 });
|
|
301
|
+
productSchema.index({ categoryId: 1 });
|
|
302
|
+
productSchema.index({ storeCategoryId: 1 });
|
|
303
|
+
productSchema.index({ deleted: 1 });
|
|
304
|
+
productSchema.index({ numberOfSales: -1 });
|
|
305
|
+
productSchema.index({ numberOfViews: -1 });
|
|
306
|
+
productSchema.index({ averageRating: -1 });
|
|
307
|
+
productSchema.index({ createdAt: -1 });
|
|
308
|
+
productSchema.index({ price: 1 });
|
|
309
|
+
productSchema.index({ tags: 1 });
|
|
310
|
+
productSchema.index({ 'variants._id': 1 });
|
|
311
|
+
|
|
298
312
|
module.exports = mongoose.model('Product', productSchema);
|
package/models/ResetPassword.js
CHANGED
|
@@ -49,4 +49,9 @@ const resetPasswordSchema = new mongoose.Schema(
|
|
|
49
49
|
{ toJSON: { virtuals: true } }
|
|
50
50
|
);
|
|
51
51
|
|
|
52
|
+
// Indexes for performance optimization
|
|
53
|
+
resetPasswordSchema.index({ userId: 1 });
|
|
54
|
+
resetPasswordSchema.index({ token: 1 });
|
|
55
|
+
resetPasswordSchema.index({ createAt: 1 }, { expireAfterSeconds: 3600 });
|
|
56
|
+
|
|
52
57
|
module.exports = mongoose.model('ResetPassword', resetPasswordSchema);
|
package/models/Sale.js
CHANGED
|
@@ -44,4 +44,11 @@ const Sale = new mongoose.Schema({
|
|
|
44
44
|
region: { type: String }
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
// Indexes for performance optimization (analytics queries)
|
|
48
|
+
Sale.index({ sellerId: 1, date: -1 });
|
|
49
|
+
Sale.index({ storeId: 1, date: -1 });
|
|
50
|
+
Sale.index({ productId: 1, date: -1 });
|
|
51
|
+
Sale.index({ date: -1 });
|
|
52
|
+
Sale.index({ region: 1 });
|
|
53
|
+
|
|
47
54
|
module.exports = mongoose.model('Sale', Sale);
|
package/models/Store.js
CHANGED
|
@@ -357,7 +357,14 @@ storeSchema.virtual('rating').get(function () {
|
|
|
357
357
|
}
|
|
358
358
|
return 0;
|
|
359
359
|
});
|
|
360
|
-
|
|
360
|
+
|
|
361
|
+
// Indexes for performance optimization
|
|
361
362
|
storeSchema.index({ location: '2dsphere' });
|
|
363
|
+
storeSchema.index({ sellerId: 1 });
|
|
364
|
+
storeSchema.index({ 'address.city': 1 });
|
|
365
|
+
storeSchema.index({ isActive: 1 });
|
|
366
|
+
storeSchema.index({ activated: 1 });
|
|
367
|
+
storeSchema.index({ storeCategorieIds: 1 });
|
|
368
|
+
storeSchema.index({ ratingSum: -1, ratingCount: -1 });
|
|
362
369
|
|
|
363
370
|
module.exports = mongoose.model('Store', storeSchema);
|
package/models/Subscription.js
CHANGED
|
@@ -189,4 +189,14 @@ const subscriptionSchema = new mongoose.Schema(
|
|
|
189
189
|
{ toJSON: { virtuals: true } }
|
|
190
190
|
);
|
|
191
191
|
|
|
192
|
+
// Indexes for performance optimization
|
|
193
|
+
subscriptionSchema.index({ storeId: 1 });
|
|
194
|
+
subscriptionSchema.index({ status: 1 });
|
|
195
|
+
subscriptionSchema.index({ endDate: 1 });
|
|
196
|
+
subscriptionSchema.index({ startDate: 1 });
|
|
197
|
+
subscriptionSchema.index({ planId: 1 });
|
|
198
|
+
subscriptionSchema.index({ paymentManagerId: 1 });
|
|
199
|
+
subscriptionSchema.index({ storeId: 1, status: 1 });
|
|
200
|
+
subscriptionSchema.index({ status: 1, endDate: 1 });
|
|
201
|
+
|
|
192
202
|
module.exports = mongoose.model('Subscription', subscriptionSchema);
|
package/models/User.js
CHANGED
|
@@ -330,5 +330,11 @@ const userSchema = new mongoose.Schema(
|
|
|
330
330
|
{ timestamps: true }
|
|
331
331
|
);
|
|
332
332
|
|
|
333
|
+
// Indexes for performance optimization
|
|
333
334
|
userSchema.index({ username: 1 }, { unique: true });
|
|
335
|
+
userSchema.index({ email: 1 }, { sparse: true });
|
|
336
|
+
userSchema.index({ phone: 1 }, { sparse: true });
|
|
337
|
+
userSchema.index({ role: 1 });
|
|
338
|
+
userSchema.index({ storeSubs: 1 });
|
|
339
|
+
|
|
334
340
|
module.exports = mongoose.model('User', userSchema);
|
package/models/UserAction.js
CHANGED
|
@@ -67,6 +67,13 @@ const UserActionSchema = new mongoose.Schema({
|
|
|
67
67
|
}
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
+
// Indexes for performance optimization
|
|
71
|
+
UserActionSchema.index({ userId: 1, timestamp: -1 });
|
|
72
|
+
UserActionSchema.index({ type: 1 });
|
|
73
|
+
UserActionSchema.index({ sessionId: 1 });
|
|
74
|
+
UserActionSchema.index({ deviceId: 1 });
|
|
75
|
+
UserActionSchema.index({ timestamp: -1 });
|
|
76
|
+
|
|
70
77
|
const UserAction = mongoose.model("UserAction", UserActionSchema);
|
|
71
78
|
|
|
72
79
|
module.exports = UserAction;
|
package/models/View.js
CHANGED
|
@@ -49,6 +49,14 @@ const viewsSchema = new mongoose.Schema({
|
|
|
49
49
|
region: { type: String }
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
// Indexes for performance optimization (analytics queries)
|
|
53
|
+
viewsSchema.index({ sellerId: 1, date: -1 });
|
|
54
|
+
viewsSchema.index({ storeId: 1, date: -1 });
|
|
55
|
+
viewsSchema.index({ productId: 1, date: -1 });
|
|
56
|
+
viewsSchema.index({ clientId: 1, date: -1 });
|
|
57
|
+
viewsSchema.index({ date: -1 });
|
|
58
|
+
viewsSchema.index({ region: 1 });
|
|
59
|
+
|
|
52
60
|
module.exports = mongoose.model('View', viewsSchema);
|
|
53
61
|
|
|
54
62
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "database-connector",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "MongoDB models package with Mongoose schemas for e-commerce applications. Includes User, Product, Store, Order and more with built-in validation and virtual properties.",
|
|
5
5
|
"main": "models/index.js",
|
|
6
6
|
"scripts": {
|