Create a Counter Collection to Store all Serialized id Fields
We start from creating a Counter
collection:
import mongoose, { Document, InferSchemaType, Schema } from "mongoose"; const counterSchema = new Schema({ _id: { type: String, required: true }, seq: { type: Number, default: 0 } }); export const CounterModel = mongoose.model('Counter', counterSchema); export async function getNextSequence(name: string): Promise<number> { const result = await CounterModel.findOneAndUpdate({ _id: name }, { $inc: { seq: 1 } }, { upsert: true }); if (!result) { throw new Error("Error in counter model"); } const seq = result.seq; return seq }
- In
Counter
collection each document will have_id
as the desired name (likeuserId
). - On
save()
a new target document, we will query forCounter
collection, add theseq
value by 1, and then inject thatseq
value into our target document.
Hook to save()
Method of a Collection
save()
Method of a CollectionWe create a hook to save()
method and perform the seq
injection by:
import mongoose, { InferSchemaType, Schema } from "mongoose"; import { getNextSequence } from "./Counter"; export const userSchema = new Schema( { id: { type: Number, required: true, unique: true, min: 1 }, name: { type: String, required: true, index: true }, email: { type: String, required: true }, passwordHash: { type: String, required: true }, }, { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }, versionKey: false, } ); userSchema.pre("save", function (next) { const doc = this; getNextSequence("userId").then(nextId => { doc.id = nextId; next(); }).catch((err) => { console.log(`getNextSequence failed: ${err}`); }) }) export type User = InferSchemaType<typeof userSchema>; export const UserModel = mongoose.model('User', userSchema);