When working with NestJS and Mongoose, one commonly used feature is the timestamps
option in schemas, which automatically manages createdAt
and updatedAt
fields. By default, Mongoose uses camelCase (createdAt
, updatedAt
) for these fields. However, you might need to follow a different naming convention, such as snake_case (created_at
, updated_at
), to align with your database's naming standards or project guidelines.
In this article, we'll explore how to customize these keys in a NestJS Mongoose schema.
Why Customize Timestamps?
- Consistency: Many teams adopt a uniform naming convention, like snake_case, for database fields.
- Legacy Compatibility: When integrating with an existing database, you may need to adhere to its naming structure.
- Readability: For some developers, snake_case is more readable and consistent with SQL-style databases.
Default Mongoose Timestamp Behavior
When you enable the timestamps
option in Mongoose, it automatically adds two fields to your schema:
createdAt
: Records the date and time when the document was created.updatedAt
: Records the date and time when the document was last updated.
By default, these fields use camelCase, which might not always fit your project requirements.
Customizing Timestamp Keys in NestJS
Mongoose allows you to rename these fields by passing an options object to the timestamps
property. Here's how to do it in a NestJS schema.
Step 1: Create the Schema
Below is an example schema for a Users
collection. We customize the timestamp fields to use snake_case (created_at
, updated_at
) instead of the default camelCase.
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { Document } from "mongoose";
// Enum for user types
export enum userTypes {
ADMIN = "admin",
CUSTOMER = "customer",
}
// Define the schema with custom timestamp keys
@Schema({
timestamps: {
createdAt: "created_at", // Rename createdAt to created_at
updatedAt: "updated_at", // Rename updatedAt to updated_at
},
})
export class Users extends Document {
@Prop({ required: true })
name: string;
@Prop({ required: true })
email: string;
@Prop({ required: true })
password: string;
@Prop({ required: true, enum: [userTypes.ADMIN, userTypes.CUSTOMER] })
type: string;
@Prop({ default: false })
isVerified: boolean;
@Prop({ default: null })
otp: string;
@Prop({ default: null })
otpExpiryTime: Date;
}
// Generate the schema
export const UserSchema = SchemaFactory.createForClass(Users);
Step 2: Explanation of the Code
Timestamps Option: The
timestamps
option in the@Schema
decorator is configured to rename the keys:createdAt
→created_at
updatedAt
→updated_at
Fields and Properties: The
Users
class contains various fields, such asname
,email
,password
,type
,isVerified
,otp
, andotpExpiryTime
. These are decorated with@Prop
to define the schema structure.SchemaFactory: The
SchemaFactory.createForClass()
method is used to convert the class into a Mongoose schema.
Benefits of Customizing Timestamp Keys
- Better Compatibility: Easily integrate with systems or databases requiring specific field names.
- Improved Consistency: Maintain consistent naming conventions across your codebase.
- Easier Querying: Adhering to a familiar naming standard simplifies database queries and debugging.
Output in the Database
When a new user is added, the document in the database will look something like this:
{
"_id": "64b1f5f4e1a05a001c1f3456",
"name": "John Doe",
"email": "johndoe@example.com",
"password": "$2b$10$...",
"type": "customer",
"isVerified": false,
"otp": null,
"otpExpiryTime": null,
"created_at": "2024-12-09T10:00:00.000Z",
"updated_at": "2024-12-09T10:00:00.000Z"
}
Common Pitfalls and Solutions
1. Forget to Set Timestamps in the Decorator
Ensure the timestamps
option is correctly defined in the @Schema
decorator. Without it, the created_at
and updated_at
fields won't appear.
2. Overwriting Default Behavior
If other parts of your application rely on the default createdAt
and updatedAt
, changing these keys might cause compatibility issues. Always coordinate with your team before making schema changes.
3. Database Constraints
When working with an existing database schema, double-check that these fields align with the expected structure.
Conclusion
Customizing timestamp keys in NestJS with Mongoose is a straightforward process that enhances flexibility and ensures compatibility with various naming conventions. By leveraging Mongoose's built-in options, you can align your application with specific project requirements or database standards.
This approach not only improves the readability and maintainability of your database structure but also helps avoid conflicts in collaborative or legacy projects. Adopting consistent naming practices like this can save time and reduce bugs down the line.