MongoDB
MongoDB

MongoDB

Aggregation in MongoDB?

  • Aggregation allows you to perform various operations on documents, such as filtering, sorting, grouping, reshaping, and modifying them.
  • Common use cases include calculating aggregate values for groups of documents.
db.employees.aggregate([ { $match: { gender: 'female' } } ]);
Example

Middleware in Mongoose

4 type of middlewares
1. Document Middleware
  • Purpose: Works on individual documents (like an instance of your model). They are triggered by actions like saving a document, removing a document, or updating one.
  • Example: Let's say you want to automatically set a "lastUpdated" timestamp every time a blog post is saved or modified.
const blogPostSchema = new mongoose.Schema({ // ... other fields lastUpdated: { type: Date, default: Date.now } }); // Pre-save middleware: Update timestamp before saving blogPostSchema.pre('save', function(next) { this.lastUpdated = Date.now(); next(); });
2. Model Middleware
  • Purpose: Works on the entire model (the blueprint for your documents). Actions like inserting multiple documents at once trigger this.
  • Example: Perhaps you want to log every time a batch of new users is added to your database:
JavaScript
const userSchema = new mongoose.Schema({ ... }); // Post-insertMany middleware: Log after a batch insert userSchema.post('insertMany', function(docs, next) { console.log(`${docs.length} new users added!`); next(); });
3. Aggregate Middleware
  • Purpose: Operates on MongoDB aggregation pipelines (when you need more complex data transformations).
  • Example: Let's say you want to add a calculated field called "totalComments" to the output of an aggregation that groups your blog posts.
JavaScript
const blogPostSchema = new mongoose.Schema({ ... }); blogPostSchema.aggregate().pre('aggregate', function() { this.pipeline().unshift({ $addFields: { totalComments: { $size: "$comments" }}}); });
4. Query Middleware
  • Purpose: Acts on query objects, getting triggered before or after running queries like .find(), .findOne(), etc.
  • Example: Let's automatically default to only fetching "active" products:
JavaScript
const productSchema = new mongoose.Schema({ ... }); productSchema.pre('find', function() { this.where({ isActive: true }); });
Important!!
  • 'pre' vs. 'post': Middlewares can be 'pre' (run before the main action) or 'post' (run after).
  • 'this' keyword: What this refers to depends on the middleware type (document, query, etc.).

Pipeline

  • A pipeline is a sequence of stages that are executed to process and transform the documents in a collection. Each stage in the pipeline performs a specific operation, such as filtering, projecting, grouping, or sorting. The output of one stage becomes the input of the next stage, allowing you to perform complex operations on your data.

Custom Functions in Mongoose Models

  • In Mongoose, you can define custom functions for your models to add functionality specific to your application's needs.
Example: Creating a custom function to find users by name
const mongoose = require('mongoose'); const Schema = mongoose.Schema; // Define a schema for the User model const userSchema = new Schema({ name: String, email: String, age: Number }); // Define a custom function 'findByName' on the schema userSchema.statics.findByName = function(name) { return this.find({ name: new RegExp(name, 'i') }); }; ////// ORRR /////// userSchema.methods.findByName = function(name) { return this.find({ name: new RegExp(name, 'i') }); }; // Create a model based on the schema const User = mongoose.model('User', userSchema); // Example usage of the custom function async function getUsersByName(name) { try { const users = await User.findByName(name); console.log(users); } catch (err) { console.error(err); } } // Usage getUsersByName('John');
ย