diff --git a/lib/constants.js b/lib/constants.js index 83a66832b55..f5f5c5a19b3 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -34,3 +34,13 @@ const queryMiddlewareFunctions = queryOperations.concat([ ]); exports.queryMiddlewareFunctions = queryMiddlewareFunctions; + +/*! + * ignore + */ + +const aggregateMiddlewareFunctions = [ + 'aggregate' +]; + +exports.aggregateMiddlewareFunctions = aggregateMiddlewareFunctions; diff --git a/lib/helpers/model/applyStaticHooks.js b/lib/helpers/model/applyStaticHooks.js index 957e94f2288..34611c3b39c 100644 --- a/lib/helpers/model/applyStaticHooks.js +++ b/lib/helpers/model/applyStaticHooks.js @@ -1,7 +1,12 @@ 'use strict'; -const middlewareFunctions = require('../../constants').queryMiddlewareFunctions; const promiseOrCallback = require('../promiseOrCallback'); +const { queryMiddlewareFunctions, aggregateMiddlewareFunctions } = require('../../constants'); + +const middlewareFunctions = [ + ...queryMiddlewareFunctions, + ...aggregateMiddlewareFunctions +]; module.exports = function applyStaticHooks(model, hooks, statics) { const kareemOptions = { @@ -10,7 +15,7 @@ module.exports = function applyStaticHooks(model, hooks, statics) { }; hooks = hooks.filter(hook => { - // If the custom static overwrites an existing query middleware, don't apply + // If the custom static overwrites an existing query/aggregate middleware, don't apply // middleware to it by default. This avoids a potential backwards breaking // change with plugins like `mongoose-delete` that use statics to overwrite // built-in Mongoose functions. diff --git a/test/model.test.js b/test/model.test.js index 8e94a876694..c2e3f68c1e8 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -10,6 +10,7 @@ const assert = require('assert'); const { once } = require('events'); const random = require('./util').random; const util = require('./util'); +const model = require('../lib/model'); const mongoose = start.mongoose; const Schema = mongoose.Schema; @@ -5861,6 +5862,35 @@ describe('Model', function() { }); + it('custom statics that overwrite aggregate functions dont get hooks by default (gh-14903)', async function() { + + const schema = new Schema({ name: String }); + + schema.statics.aggregate = function(pipeline) { + return model.aggregate.apply(this, [pipeline]); + }; + + let called = 0; + schema.pre('aggregate', function(next) { + ++called; + next(); + }); + const Model = db.model('Test', schema); + + await Model.create({ name: 'foo' }); + + const res = await Model.aggregate([ + { + $match: { + name: 'foo' + } + } + ]); + + assert.ok(res[0].name); + assert.equal(called, 1); + }); + it('error handling middleware passes saved doc (gh-7832)', async function() { const schema = new Schema({ _id: Number });