I have two models - Post and User, every post has a User. Post has user id. I want to create a custom static/instance method in Post model so I can populate only several properties of User - id, name, image.
I want to implement it something like example below. But I don't see this method after find()
PostSchema.method("populateAuthorProfile", function () {
return this.populate("author", { id: 1, slug: 1, name: 1, image: 1 });
});
...
...
const posts = await PostModel.find().populateAuthorProfile();
Post model
const mongooseSlugUpdater = require("mongoose-slug-updater");
import mongoose, { Model, Schema, model } from "mongoose";
interface IPost {
title: string;
description: string;
body: string;
created: Date;
updated: Date;
image: string;
slug: string;
parent?: mongoose.Types.ObjectId;
author: mongoose.Types.ObjectId;
children: mongoose.Types.ObjectId;
tags: mongoose.Types.ObjectId[];
likes: mongoose.Types.ObjectId[];
}
// post instance methods
interface IPostMethods {
populateAuthorProfile: () => any;
}
// post static methods
interface IPostModel extends Model<IPost, {}, IPostMethods> {
findBySlug: (slug: string) => any;
}
const PostSchema = new Schema<IPost, IPostModel, IPostMethods>({
title: { type: String, trim: true, required: true },
description: { type: String, trim: true, required: true },
body: { type: String, trim: true, required: true },
created: { type: Date, default: Date.now() },
updated: { type: Date },
image: { type: String },
slug: { type: String, slug: "title", slugPaddingSize: 4, unique: true },
parent: {
type: Schema.Types.ObjectId,
ref: "Post",
},
author: {
type: Schema.Types.ObjectId,
ref: "User",
},
tags: [
{
type: Schema.Types.ObjectId,
ref: "Tag",
},
],
likes: [
{
type: Schema.Types.ObjectId,
ref: "User",
},
],
children: {
type: Schema.Types.ObjectId,
ref: "Post",
},
});
// methods
PostSchema.method("populateAuthorProfile", function () {
return this.populate("author", { id: 1, slug: 1, name: 1, image: 1 });
});
// statics
PostSchema.static("findBySlug", function (slug: string) {
return this.findOne({ slug: slug });
});
PostSchema.plugin(mongooseSlugUpdater);
PostSchema.set("toJSON", {
transform: (_document, returnedObject) => {
returnedObject.id = returnedObject._id.toString();
delete returnedObject._id;
delete returnedObject.__v;
},
});
const PostModel = model<IPost, IPostModel>("Post", PostSchema);
export default PostModel;
User model
import mongoose, { Model, Schema, model } from "mongoose";
const mongooseSlugUpdater = require("mongoose-slug-updater");
// user schema
interface IUser {
name: string;
bio?: string;
email: string;
image?: string;
passwordHash?: string;
emailVerified?: boolean;
created: Date;
updated?: Date;
slug: string;
roles: mongoose.Types.ObjectId[];
posts: mongoose.Types.ObjectId[];
likedPosts: mongoose.Types.ObjectId[];
accounts: mongoose.Types.ObjectId[];
}
interface IUserAccount {
id: string;
name: string;
email: string;
image?: string;
roles: mongoose.Types.ObjectId[];
}
// user instance methods
interface IUserMethods {
toUserAccount: () => IUserAccount;
}
// user static methods
interface IUserModel extends Model<IUser, {}, IUserMethods> {
findByEmail: (email: string) => any;
}
const UserSchema = new Schema<IUser, IUserModel, IUserMethods>({
name: { type: String },
bio: { type: String },
email: { type: String, required: true, unique: true },
image: { type: String },
passwordHash: { type: String },
emailVerified: { type: Boolean, default: false },
created: { type: Date, default: Date.now() },
updated: { type: Date },
slug: { type: String, slug: "email", slugPaddingSize: 4, unique: true },
roles: [
{
type: Schema.Types.ObjectId,
ref: "Role",
},
],
posts: [
{
type: Schema.Types.ObjectId,
ref: "Post",
},
],
likedPosts: [
{
type: Schema.Types.ObjectId,
ref: "Post",
},
],
accounts: [
{
type: Schema.Types.ObjectId,
ref: "Account",
},
],
});
// methods
UserSchema.method("toUserAccount", function () {
const userAccout: IUserAccount = {
id: this._id.toString(),
name: this.name,
email: this.email,
image: this.image,
roles: this.roles,
};
return userAccout;
});
// statics
UserSchema.static("findByEmail", function (email: string) {
return this.findOne({ email: email });
});
UserSchema.plugin(mongooseSlugUpdater);
UserSchema.set("toJSON", {
transform: (_document, returnedObject) => {
returnedObject.id = returnedObject._id.toString();
delete returnedObject._id;
delete returnedObject.passwordHash;
delete returnedObject.__v;
},
});
const UserModel = model<IUser, IUserModel>("User", UserSchema);
export default UserModel;