Mongoose 'static' methods vs. 'instance' methods

Well to me it doesn't mean add anythings by adding Mongoose in front of 'static' or even in front 'instance' keyword.

What I believe meaning and purpose of static is same everywhere, even it's also true for an alien language or some sort of driver which represents Model for building the block like another object-oriented programming. The same also goes for instance.

From Wikipedia: A method in object-oriented programming (OOP) is a procedure associated with a message and an object. An object consists of data and behavior. The data and behavior comprise an interface, which specifies how the object may be utilized by any of various consumers[1] of the object.

Data is represented as properties of the object and behaviors are represented as methods of the object. For example, a Window object could have methods such as open and close, while its state (whether it is opened or closed at any given point in time) would be a property.

Static methods are meant to be relevant to all the instances of a class rather than to any specific instance. They are similar to static variables in that sense. An example would be a static method to sum the values of all the variables of every instance of a class. For example, if there were a Product class it might have a static method to compute the average price of all products.

Math.max(double a, double b)

This static method has no owning object and does not run on an instance. It receives all information from its arguments.[7]

A static method can be invoked even if no instances of the class exist yet. Static methods are called "static" because they are resolved at compile time based on the class they are called on and not dynamically as in the case with instance methods, which are resolved polymorphically based on the runtime type of the object.

https://en.wikipedia.org/wiki/Method_(computer_programming)


Database logic should be encapsulated within the data model. Mongoose provides 2 ways of doing this, methods and statics. Methods adds an instance method to documents whereas Statics adds static “class” methods to the Models itself.The static keyword defines a static method for a model. Static methods aren't called on instances of the model. Instead, they're called on the model itself. These are often utility functions, such as functions to create or clone objects. like example below:

const bookSchema = mongoose.Schema({
  title: {
    type : String,
    required : [true, 'Book name required']
  },
  publisher : {
    type : String,
    required : [true, 'Publisher name required']
  },
  thumbnail : {
    type : String
  }
  type : {
    type : String
  },
  hasAward : {
    type : Boolean
  }
});

//method
bookSchema.methods.findByType = function (callback) {
  return this.model('Book').find({ type: this.type }, callback);
};

// statics
bookSchema.statics.findBooksWithAward = function (callback) {
  Book.find({ hasAward: true }, callback);
};

const Book = mongoose.model('Book', bookSchema);
export default Book;

for more info: https://osmangoni.info/posts/separating-methods-schema-statics-mongoose/


statics are the methods defined on the Model. methods are defined on the document (instance).

You might use a static method like Animal.findByName:

const fido = await Animal.findByName('fido');
// fido => { name: 'fido', type: 'dog' }

And you might use an instance method like fido.findSimilarTypes:

const dogs = await fido.findSimilarTypes();
// dogs => [ {name:'fido',type:'dog} , {name:'sheeba',type:'dog'} ]

But you wouldn't do Animals.findSimilarTypes() because Animals is a model, it has no "type". findSimilarTypes needs a this.type which wouldn't exist in Animals model, only a document instance would contain that property, as defined in the model.

Similarly you wouldn't¹ do fido.findByName because findByName would need to search through all documents and fido is just a document.

¹Well, technically you can, because instance does have access to the collection (this.constructor or this.model('Animal')) but it wouldn't make sense (at least in this case) to have an instance method that doesn't use any properties from the instance. (thanks to @AaronDufour for pointing this out)