Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongoose schema check if model instance is saved for the first time

I have 3 schemas, 2 of which have a .pre('save') hook to push its _id into the previous one's. You can take the example of a forum with topics, questions and comments

var topicSchema = new Schema({
  arr: {type:[Schema.ObjectId], ref:'Question'},
});
var Topic = new mongoose.model('Topic', topicSchema);

var questionSchema = new Schema({
  targetId: {type:Schema.ObjectId, ref:'Topic', required:true},
  arr: {type:[Schema.ObjectId], ref:'Comment'},
});
var Question = new mongoose.model('Question', questionSchema);

var commentSchema = new Schema({
  targetId: {type:Schema.ObjectId, ref:'Question', required:true},
});
var Comment = new mongoose.model('Comment', commentSchema);

Now for the above schema I want: When I save a question I want to automatically push the question's _id to its respective Topic.arr and when I save a comment to auto push its it to its respective Question.arr

I've tried solving this using .pre('save') hooks as follows:

function addPreSave (schema, idProperty, containerProperty) {
  var modelName = schema.paths[idProperty].options.ref;
  var model = mongoose.models[modelName];

  schema.pre('save', function (next) {
    model.findById(this[idProperty], function (err, doc) {
      doc[containerProperty].push(this._id);
      doc.save(next);
    }.bind(this));
  });
}

addPreSave(questionSchema, 'targetId', 'arr');
addPreSave(commentSchema, 'targetId', 'arr');

All that the above function does (and the 2 calls to it) is to add a .pre('save') hook to each of the 2 schemas to add their _id in their respective parent.


THE ISSUE: The problem is that now, every time I save a comment, it pushes its id to the topic, but I only actually want to do this the very first time only. So in the above example if you create a topic, then a question for it and then a comment for the question, the Topic.arr will have 2 ids in it (twice the question's _id) as it saves once for the question and a second time it's triggered by the comment's call to save the question

Does anyone know a way around this, or more specifically if you know how to figure out in the pre-save hook if this is a first-time save or not?

like image 376
Stefan Avatar asked Jan 25 '14 10:01

Stefan


People also ask

How do I get the ObjectId after I save an object in Mongoose?

To get the object ID after an object is saved in Mongoose, we can get the value from the callback that's run after we call save . const { Schema } = require('mongoose') mongoose. connect('mongodb://localhost/lol', (err) => { if (err) { console. log(err) } }); const ChatSchema = new Schema({ name: String }); mongoose.

What is __ V in MongoDB?

The __v field is called the version key. It describes the internal revision of a document.

What is versionKey in Mongoose?

The versionKey is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The name of this document property is configurable.

What is Mongoose schema ObjectId?

ObjectId . A SchemaType is just a configuration object for Mongoose. An instance of the mongoose. ObjectId SchemaType doesn't actually create MongoDB ObjectIds, it is just a configuration for a path in a schema.


1 Answers

So it turns out that you can find the answer to anything if you are willing to go on the second page of Google!

There is a property defined for every document called isNew which does what you might imagine. So just adding a if (!this.isNew) return next() in the method fixes the issue.

like image 198
Stefan Avatar answered Oct 01 '22 08:10

Stefan