ITADN

Support pre('bulkWrite') middleware hook on schemas

#16225Openslyjain 创建于 2026-04-09
new featureenhancementcan't reproduceStale
S
slyjaincommented
### Prerequisites - [x] I have written a descriptive issue title - [x] I have searched existing issues to ensure the feature has not already been requested ### 🚀 Feature Proposal Mongoose supports pre() middleware hooks for most query operations (find, updateOne, deleteMany, etc.), aggregate, save, and insertMany , but not for bulkWrite. Since Model.bulkWrite() bypasses all schema-level middleware, there's no way to intercept or modify bulk operations at the schema layer. This means any cross-cutting concern implemented via schema hooks (tenant isolation, soft-delete filters, audit logging, etc.) silently breaks when bulkWrite is used. Developers must implement application-layer workarounds to replicate what hooks do for every other operation. ### Motivation We're building multi-tenant isolation using schema pre() hooks to auto-inject a tenant filter (id.clientId) on all queries. This works for all 13 query types, aggregate, save, and insertMany ,but not bulkWrite. We had to implement tenant injection at the application layer specifically for bulkWrite, creating an inconsistency where every other Mongoose operation is protected at the schema level but bulkWrite requires a separate code path. This affects anyone using schema middleware for: - Multi-tenant isolation (filter injection) - Soft-delete patterns (auto-add { deleted: false }) - Audit logging (track who modified what) - Field-level access control ### Example ```js const schema = new Schema({ id: { clientId: { type: Schema.Types.ObjectId, required: true }, }, name: String, }); // This works for find, updateOne, deleteMany, etc. schema.pre('find', function () { this.where({ 'id.clientId': getCurrentTenantId() }); }); // This does NOT exist today — bulkWrite bypasses all middleware schema.pre('bulkWrite', function (next, ops) { ops.forEach(op => { if (op.updateOne) { op.updateOne.filter['id.clientId'] = getCurrentTenantId(); } if (op.insertOne) { op.insertOne.document['id.clientId'] = getCurrentTenantId(); } // ... same for deleteOne, updateMany, etc. }); next(); }); ``` The pre('bulkWrite') hook would receive the operations array and allow modification before execution, consistent with how pre('insertMany') receives the docs array.
3 条评论