According to the mongoose docs, there are 3 ways to add custom methods to your documents:
- Through schema options
- Directly assigning a "methods" object to the schema
- Using the Schema.method() helper
However, after many tries, I have only managed to get methods working using option 1. I am curious as to why options 2 & 3 are not working for me. here is my code:
app.js
socket.on("message", async function (clusterData, callback) {
console.log("socket event fired");
const parentCluster = await Message.findById(clusterData.clusterId);
coonsole.log(parentCluster); // exists as expected
parentCluster.optionsMethod(); // log : "options method called" ✔
parentCluster.objectMethod(); // error : parentCluster.objectMethod is not a function ❌
parentCluster.helperMethod(); // error : parentCluster.helperMethod is not a function ❌
});
Message.js
import mongoose from "mongoose";
const messageSchema = new mongoose.Schema({
mentions: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
text: { type: String, trim: true },
file: { type: String },
dateString: { type: String, required: true },
timestamp: { type: Number, required: true },
});
const messageClusterSchema = new mongoose.Schema(
{
sender: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
channel: {
type: mongoose.Schema.Types.ObjectId,
ref: "Channel",
required: true,
},
group: {
type: mongoose.Schema.Types.ObjectId,
ref: "Group",
required: true,
},
content: [messageSchema],
clusterTimestamp: {
type: Number,
required: true,
},
},
{
toObject: { virtuals: true },
toJSON: { virtuals: true },
methods: {
optionsMethod() {
console.log("options method called");
},
},
}
);
messageClusterSchema.virtual("lastMessage").get(function () {
return this.content[this.content.length - 1];
});
messageClusterSchema.pre("validate", function () {
console.log("pre validate ran");
this.clusterTimestamp = this.content[this.content.length - 1].timestamp;
});
// assign directly to object
messageSchema.methods.objectMethod = function () {
console.log("object method called");
};
// assign with helper
messageSchema.method("helperMethod", function () {
console.log("helper method called");
});
console.log(messageSchema.methods); // {objectMethod: [Function (anonymous)], helperMethod: [Function (anonymous)]}
console.log(messageSchema.methodOptions); // { helperMethod: undefined }
const Message = mongoose.model("Message", messageClusterSchema);
export default Message;
CodePudding user response:
The issue is that,
objectMethod
and helperMethod
is in messageSchema
and In Message.js file, you are creating model of messageClusterSchema
which you are importing and using in socket function. Both methods can only be called with a model-instance of messageSchema
. And that's why optionsMethod
is calling, but the other two are not. Basically you need to create model of messageSchema
and export it to use it in other files.
In short, the error is:
const Message = mongoose.model("Message", messageClusterSchema);
The model is generated using messageClusterSchema
, but the methods are assigned to messageSchema
:
messageSchema.methods.objectMethod = function () {
console.log("object method called");
};
// assign with helper
messageSchema.method("helperMethod", function () {
console.log("helper method called");
});
They should be assigned to messageClusterSchema
.