Projection in MongoDB is a way to specify which fields should be returned in the results of a query. It helps to reduce the amount of data that needs to be transferred over the network and processed by your application. By default, queries in MongoDB return all fields in the matching documents.
It’s required that each schema definition should also have a projection defined with the default projections. This practice helps in maintaining a consistent approach across different schemas, making the codebase easier to manage and understand. Furthermore, accessing documents only through these projections is crucial for security reasons. For instance, in the user schema, the projection should ensure that the password field is never returned. By adhering to this requirement, you ensure that sensitive data remains protected while optimizing the data retrieval process for better performance and security.

Syntax:

The basic syntax of a projection is to specify the field name and set a value of 1 or true to include the field in the result, and 0 or false to exclude it.
{ field1: 1, field2: 0 }
Example: In a NestJS application using Mongoose, you can specify projection in a query like so:
const projection = { name: 1, email: 1 };  // Include only name and email fields
const users = await UserModel.find({}, projection);

PropertyProtection Class Explanation:

In the provided code snippet, the ExampleSchema class is utilized to define different sets of projections based on the use-case. This class has static methods that return objects representing projections. Defining Projections: In the ExampleSchema class, projections are defined using static methods. Here’s how it’s done:
export class ExampleSchema {
  private static getDefaultProtection() {
    return {
      password: 0,
    };
  }

  private static getDashboardProtection() {
    return {
      firstName: 1,
      lastName: 1,
    };
  }

  static DEFAULT(): any {
    return {
      ...this.getDefaultProtection(),
    };
  }

  static DASHBOARD(): any {
    return {
      ...this.getDashboardProtection(),
    };
  }

  ....
}
Usage:
user = this.userService({
  conditions: {
    _id: user._id,
  },
  projection: UserProtection.DEFAULT(),
});

Custom Projections:

You can also create custom projections based on your requirements. For example, if you need a projection that only includes a user’s name and email, you could define a method in your protection class like so:
static NAME_AND_EMAIL(): any {
  return { name: 1, email: 1 };
}
This way, you can have pre-defined projection sets for different scenarios, while also having the flexibility to define and use custom projections as needed.