My express application needs to list the number of users I currently have in my mongo database. That works fine when I ask for a small number of users (i.e. ~100), but if I ask for numbers in the tens of thousands I begin to see a huge delay in the response time. For instance, it takes about 19 seconds to retrieve 25,000 users.
Is it normal to have this kind of performance in mongo, or should I suspect I have a bug somewhere?
Here's my model:
'use strict';
// External modules
const mongoose = require('mongoose');
const encrypt = require('mongoose-encryption');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
uuid: {
type: String,
trim: true,
// TODO: test for unique uuid
index: { unique: true },
required: 'uuid cannot be blank'
},
createdOn: {
type: Date,
default: Date.now,
index: true
},
email: {
type: String,
trim: true,
required: 'email cannot be blank'
},
lists: [{
type: Schema.Types.ObjectId,
ref: 'List'
}]
});
UserSchema.index({ "lists" : 1 , "createdOn" : 1});
UserSchema.plugin(encrypt, { encryptionKey: process.env.EMAIL_ENCRYPTION_KEY, signingKey: process.env.EMAIL_SIGNING_KEY, encryptedFields: ['email'] });
mongoose.model('User', UserSchema);
And here's my query:
exports.list = (req, res) => {
let page = (Number(req.query.p) > 0 ? Number(req.query.p) : 1) - 1;
let perPage = (Number(req.query.pp) > 0 ? Number(req.query.pp) : 100);
res.header('X-Page', page + 1);
res.header('X-Per-Page', perPage);
User.count({}, (countErr, count) => {
res.header('X-Total-Count', count);
User.find({}, { __v: 0, createdOn: 0})
.sort({'createdOn': 1})
.limit(perPage)
.skip(perPage * page)
.exec((err, users) => {
if (err) {
return res.status(400).send({
message: err
});
}
else {
res.json(users);
}
});
});
};
When profiling, the count()
operation takes about 52ms, hence, most of the time is spent in the find()
query.