Shauryan Singh
Shauryan Singh

Reputation: 1

Mongoose Instance methods

Instance methods

// define a schema
const animalSchema = new Schema({ name: String, type: String });

// assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function(cb) {
return mongoose.model('Animal').find({ type: this.type }, cb);
};

Now all of our animal instances have a findSimilarTypes method available to them.

const Animal = mongoose.model('Animal', animalSchema);
const dog = new Animal({ type: 'dog' });

dog.findSimilarTypes((err, dogs) => {
console.log(dogs); // woof

});

I was reading the docs of mongoose and I'm not able to understand the work of this piece of code. Can anyone explain it to me.

Someone explain flow of this code

Upvotes: 0

Views: 4589

Answers (4)

Change into the conventional function if you are using arrow function

Correct:

schema.methods.myMethod = async function () {
  console.log('this', this);
};

Wrong:

schema.methods.myMethod = async () => {
  console.log('this', this);
};

Upvotes: 0

Xavier Chia
Xavier Chia

Reputation: 257

I filled in the gaps with the Mongoose documentation so that you can run this on your own machine. The only missing piece here is to add the url for connection.

  // define a schema
const animalSchema = new mongoose.Schema({ name: String, type: String },
  {
    // Assign a function to the "methods" object of our animalSchema through schema options.
    // By following this approach, there is no need to create a separate TS type to define the type of the instance functions.
    methods: {
      findSimilarTypes(cb) {
        return mongoose.model('Animal').find({ type: this.type }, cb);
      }
    }
  });
  
const Animal = mongoose.model('Animal', animalSchema);

// Creating 2 dogs and a cat
const dog = new Animal({ name: 'joe', type: 'dog' });
const dog2 = new Animal({ name: 'joe2', type: 'dog' });
const cat = new Animal({ name: 'bob', type: 'cat'});

mongoose.connect(url)
.then((result) => {
  console.log("connected")
  // Saving our animals to the database
  return Animal.insertMany([dog, dog2, cat])
}).then(() => {
  // Find similar animals to that of `dog`
  dog.findSimilarTypes((err, dogs) => {
    if (err) {
      console.log(err)
    } else {
      console.log(dogs); // you should log two dogs, joe and joe2
    }
  });
})

Upvotes: 0

Antti_M
Antti_M

Reputation: 978

// define a schema
const animalSchema = new Schema({ name: String, type: String });

Define the Animal schema: what fields and features does an animal object have when saved to the database.

// assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function(cb) {
    return mongoose.model('Animal').find({ type: this.type }, cb);
};

Define that each object created with the animal recipe should also have a method called findSimilarTypes(callback).

const Animal = mongoose.model('Animal', animalSchema);
const dog = new Animal({ type: 'dog' });

dog.findSimilarTypes((err, dogs) => {
    console.log(dogs); // woof
});
  • When you call mongoose.model() on a schema, Mongoose compiles a model for you. This allows you to create new objects that can be saved to the database, but does not save a new object to the database yet.
  • Then a new animal object is created, called dog. It has type 'dog' Notice that dog.findSimilarTypes(cb) also exists, as defined in the schema.
  • The method is called, and it will return all objects that have the same type as the object dog.

Addition, to address Shauryan's additional question in the comments:

You can check for example this resource to understand what a callback funtion is: Callback function. I'll try my best to explain what happens in your example.

findSimilarTypes(cb) is a function that takes a single parameter, which also is a function.

This guy here is a single, anonymous function.

(err, dogs) => {
    console.log(dogs); // woof
}

When you pass a function as an argument, it's called a "callback". Let's see what you get when you call findSimilarTypes(cb) with the anonymous function as the argument.

animalSchema.methods.findSimilarTypes = function(cb) {
    return mongoose.model('Animal').find({ type: this.type }, cb);
};

becomes something like this (when you replace the cb with the anonymous function):

return mongoose.model('Animal').find({ type: this.type }, (err, dogs) => {
    console.log(dogs); // woof
});

Now it comes down to how Mongoose has defined its Model.find(). When it's done, it calls its second argument with the error and result of the database search. The second argument is the anonymous function we passed on earlier.

It takes a little time to twist your head around callbacks. Hope this helps!

Upvotes: 2

Nico Krätschmer
Nico Krätschmer

Reputation: 156

Schemas have a field called methods. In that field you can insert your own functions like so:

animalSchema.methods.nameOfFunction = function() {
   // Return something here  
   // The `this` keyword refers to the instance of the model
   // I return the type here
   return this.type;
};

Later when you create a instance of the Schema you can use them.

// animalSchema is the Schema we inserted the function into earlier
// create model from instance
const Animal = mongoose.model('Animal', animalSchema);

// Create ab Instance of the model 
// the function added to the methods field gets added
// The dog gets created with type 'dog'
const dog = new Animal({ type: 'dog' });

// Now we can call the function
// the `this` in the function referes to `dog`
var result = dog.nameOfFunction();
// Will put out "dog"
console.log(result)

In the example you provided the function added finds all Animals with the same type as the animal created. The cbargument of the function is a callback. Another function that gets called when mongoose finished searching.

Upvotes: 2

Related Questions