class CParamsQuery { constructor(params) { this.startRow = params.startRow; this.endRow = params.endRow; // this.count = params.count; this.filter = params.filter; this.sortBy = params.sortBy; this.descending = params.descending; } } /** * Query blog posts by user -> paginated results and a total count. * @param userId {ObjectId} ID of user to retrieve blog posts for * @param startRow {Number} First row to return in results * @param endRow {Number} Last row to return in results * @param [filter] {Object} Optional extra matching query object * @param [sort] {Object} Optional sort query object * @returns {Object} Object -> `{ rows, count }` */ function queryBlogPostsByUser (userId, startRow, endRow, filter = {}, sort = false) { const User = this; if (!(user instanceof mongoose.Types.ObjectId)) { throw new Error('userId must be ObjectId') } else if (typeof startRow !== 'number') { throw new Error('startRow must be number') } else if (typeof endRow !== 'number') { throw new Error('endRow must be number') } const query = [ // more lookups go here if you need them // we have a many-to-one from blogPost -> user { $lookup: { from: 'users', localField: 'user', foreignField: '_id', as: 'user' } }, // each blog has a single user (author) so flatten it using $unwind { $unwind: '$user' }, // filter the results by our userId { $match: Object.assign({ 'user._id': userId }, filter) } ]; if (sort) { // maybe we want to sort by blog title or something query.push({ $sort: sort }) } query.push( { $group: { _id: null, // get a count of every result that matches until now count: { $sum: 1 }, // keep our results for the next operation results: { $push: '$$ROOT' } } }, // and finally trim the results to within the range given by start/endRow { $project: { count: 1, rows: { $slice: ['$results', startRow, endRow] } } } ); return User .aggregate(query) .then(([{ count, rows }]) => ({ count, rows })) }; module.exports = { CParamsQuery, queryBlogPostsByUser };