If you haven't yet done so, please take a minute to read the quickstart to get an idea of how Mongoose works. If you are migrating from 7.x to 8.x please take a moment to read the migration guide.
Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.
import mongoose from 'mongoose';
const { Schema } = mongoose;
const blogSchema = new Schema[{
title: String, // String is shorthand for {type: String}
author: String,
body: String,
comments: [{ body: String, date: Date }],
date: { type: Date, default: Date.now },
hidden: Boolean,
meta: {
votes: Number,
favs: Number
}
}];
If you want to add additional keys later, use the method.
Each key in our code
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
6 defines a property in our documents which will be cast to its associated . For example, we've defined a property
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
7 which will be cast to the SchemaType and property
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
8 which will be cast to a
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
9 SchemaType.
Notice above that if a property only requires a type, it can be specified using a shorthand notation [contrast the
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
7 property above with the
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
8 property].
Keys may also be assigned nested objects containing further key/type definitions like the
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
2 property above. This will happen whenever a key's value is a POJO that doesn't have a
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
3 property.
In these cases, Mongoose only creates actual schema paths for leaves in the tree. [like
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
4 and
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
5 above], and the branches do not have actual paths. A side-effect of this is that
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
2 above cannot have its own validation. If validation is needed up the tree, a path needs to be created up the tree - see the Subdocuments section for more information on how to do this. Also read the Mixed subsection of the SchemaTypes guide for some gotchas.
The permitted SchemaTypes are:
Read more about SchemaTypes here.
Schemas not only define the structure of your document and casting of properties, they also define document , , , and document lifecycle hooks called middleware.
To use our schema definition, we need to convert our
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
6 into a Model we can work with. To do so, we pass it into
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
8:
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
By default, Mongoose adds an
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9 property to your schemas.
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
When you create a new document with the automatically added
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9 property, Mongoose creates a new
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9 of type ObjectId to your document.
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
You can also overwrite Mongoose's default
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9 with your own
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9. Just be careful: Mongoose will refuse to save a document that doesn't have an
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9, so you're responsible for setting
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9 if you define your own
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9 path.
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
Instances of
const animalSchema = new Schema[{
name: String,
type: String,
tags: { type: [String], index: true } // path level
}];
animalSchema.index[{ name: 1, type: -1 }]; // schema level
7 are documents. Documents have many of their own built-in instance methods. We may also define our own custom document instance methods.
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, 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
const animalSchema = new Schema[{
name: String,
type: String,
tags: { type: [String], index: true } // path level
}];
animalSchema.index[{ name: 1, type: -1 }]; // schema level
8 instances have a
const animalSchema = new Schema[{
name: String,
type: String,
tags: { type: [String], index: true } // path level
}];
animalSchema.index[{ name: 1, type: -1 }]; // schema level
9 method available to them.
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
- Overwriting a default mongoose document method may lead to unpredictable results. See for more details.
- The example above uses the
const Blog = mongoose.model['Blog', blogSchema]; // ready to go!
00 object directly to save an instance method. You can also use the
01 helper as described .const Blog = mongoose.model['Blog', blogSchema]; // ready to go!
- Do not declare methods using ES6 arrow functions [
02]. Arrow functions , so your method will not have access to the document and the above examples will not work.const Blog = mongoose.model['Blog', blogSchema]; // ready to go!
You can also add static functions to your model. There are three equivalent ways to add a static:
- Add a function property to the second argument of the schema-constructor [
04]const Blog = mongoose.model['Blog', blogSchema]; // ready to go!
- Add a function property to
05const Blog = mongoose.model['Blog', blogSchema]; // ready to go!
- Call the
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
Do not declare statics using ES6 arrow functions [
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
02]. Arrow functions , so the above examples will not work because of the value of
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
03.
You can also add query helper functions, which are like instance methods but for mongoose queries. Query helper methods let you extend mongoose's chainable query builder API.
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
MongoDB supports secondary indexes. With mongoose, we define these indexes within our
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
10 or the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
11 level. Defining indexes at the schema level is necessary when creating compound indexes.
const animalSchema = new Schema[{
name: String,
type: String,
tags: { type: [String], index: true } // path level
}];
animalSchema.index[{ name: 1, type: -1 }]; // schema level
See for other index options.
When your application starts up, Mongoose automatically calls for each defined index in your schema. Mongoose will call
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
12 for each index sequentially, and emit an 'index' event on the model when all the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
12 calls succeeded or when there was an error. While nice for development, it is recommended this behavior be disabled in production since index creation can cause a . Disable the behavior by setting the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
15 option of your schema to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
16, or globally on the connection by setting the option
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
15 to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
16.
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
0
Mongoose will emit an
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
19 event on the model when indexes are done building or an error occurred.
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
1
See also the method.
are document properties that you can get and set but that do not get persisted to MongoDB. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage.
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
2
Suppose you want to print out the person's full name. You could do it yourself:
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
3
But concatenating the first and last name every time can get cumbersome. And what if you want to do some extra processing on the name, like removing diacritics? A lets you define a
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
20 property that won't get persisted to MongoDB.
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
4
Now, mongoose will call your getter function every time you access the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
20 property:
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
5
If you use
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
22 or
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
23 Mongoose will not include virtuals by default. Pass
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
24 to or
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
23 to include virtuals.
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
6
The above caveat for
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
22 also includes the output of calling
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
28 on a Mongoose document, because . To include virtuals in
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
28 output, you can either call
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
32 on the document before calling
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
28, or set the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
34 option on your schema.
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
7
You can also add a custom setter to your virtual that will let you set both first name and last name via the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
20 virtual.
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
8
Virtual property setters are applied before other validation. So the example above would still work even if the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
36 and
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
37 name fields were required.
Only non-virtual properties work as part of queries and for field selection. Since virtuals are not stored in MongoDB, you can't query with them.
You can learn more about virtuals here.
Aliases are a particular type of virtual where the getter and setter seamlessly get and set another property. This is handy for saving network bandwidth, so you can convert a short property name stored in the database into a longer name for code readability.
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
9
You can also declare aliases on nested paths. It is easier to use nested schemas and subdocuments, but you can also declare nested path aliases inline as long as you use the full nested path
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
38 as the alias.
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
0
Schemas have a few configurable options which can be passed to the constructor or to the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
39 method:
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
1
Valid options:
By default, Mongoose's creates all the indexes defined in your model's schema by calling after you successfully connect to MongoDB. Creating indexes automatically is great for development and test environments. But index builds can also create significant load on your production database. If you want to manage indexes carefully in production, you can set
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
15 to false.
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
2
The
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
15 option is set to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
44 by default. You can change this default by setting
Before Mongoose builds indexes, it calls
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
46 to create the underlying collection in MongoDB by default. Calling
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
47 sets the collection's default collation based on the and establishes the collection as a capped collection if you set the .
You can disable this behavior by setting
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
49 to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
16 using . Like
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
15,
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
49 is helpful for development and test environments, but you may want to disable it for production to avoid unnecessary database calls.
Unfortunately,
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
47 cannot change an existing collection. For example, if you add
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
55 to your schema and the existing collection is not capped,
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
47 will not overwrite the existing collection. That is because the MongoDB server does not allow changing a collection's options without dropping the collection first.
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
3
By default, mongoose buffers commands when the connection goes down until the driver manages to reconnect. To disable buffering, set
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
57 to false.
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
4
The schema
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
57 option overrides the global
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
57 option.
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
5
If
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
57 is on, this option sets the maximum amount of time Mongoose buffering will wait before throwing an error. If not specified, Mongoose will use 10000 [10 seconds].
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
6
Mongoose supports MongoDBs capped collections. To specify the underlying MongoDB collection be
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
48, set the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
48 option to the maximum size of the collection in .
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
7
The
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
48 option may also be set to an object if you want to pass additional options like . In this case you must explicitly pass the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
64 option, which is required.
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
8
Mongoose by default produces a collection name by passing the model name to the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
65 method. This method pluralizes the name. Set this option if you need a different name for your collection.
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
9
When you define a discriminator, Mongoose adds a path to your schema that stores which discriminator a document is an instance of. By default, Mongoose adds an
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
66 path, but you can set
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
67 to overwrite this default.
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
0
When
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
68 is
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
44, Mongoose will not create indexes from the given subdocument schema. This option only works when the schema is used in a subdocument path or document array path, Mongoose ignores this option if set on the top-level schema for a model. Defaults to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
16.
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
1
Mongoose assigns each of your schemas an
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
71 virtual getter by default which returns the document's
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9 field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
71 getter added to your schema, you may disable it by passing this option at schema construction time.
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
2
Mongoose assigns each of your schemas an
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9 field by default if one is not passed into the constructor. The type assigned is an to coincide with MongoDB's default behavior. If you don't want an
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9 added to your schema at all, you may disable it using this option.
You can only use this option on subdocuments. Mongoose can't save a document without knowing its id, so you will get an error if you try to save a document without an
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "query" 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 query functions.
query: {
byName[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "query" object of our animalSchema
animalSchema.query.byName = function[name] {
return this.where[{ name: new RegExp[name, 'i'] }];
};
const Animal = mongoose.model['Animal', animalSchema];
Animal.find[].byName['fido'].exec[[err, animals] => {
console.log[animals];
}];
Animal.findOne[].byName['fido'].exec[[err, animal] => {
console.log[animal];
}];
9.
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
3
Mongoose will, by default, "minimize" schemas by removing empty objects.
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
4
This behavior can be overridden by setting
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
77 option to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
16. It will then store empty objects.
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
5
To check whether an object is empty, you can use the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
79 helper:
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
6
Allows setting options at the schema level, providing us a way to apply default to all queries derived from a model.
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
7
The alias of each pref is also permitted so instead of having to type out 'secondaryPreferred' and getting the spelling wrong, we can simply pass 'sp'.
The read option also allows us to specify tag sets. These tell the driver from which members of the replica-set it should attempt to read. Read more about tag sets and here.
NOTE: you may also specify the driver read preference option when connecting:
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
8
Allows setting write concern at the schema level.
const Model = mongoose.model['Test', schema];
const doc = new Model[];
doc._id instanceof mongoose.Types.ObjectId; // true
9
The
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
80 option is used when we have a sharded MongoDB architecture. Each sharded collection is given a shard key which must be present in all insert/update operations. We just need to set this schema option to the same shard key and we’ll be all set.
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
0
Note that Mongoose does not send the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
81 command for you. You must configure your shards yourself.
The strict option, [enabled by default], ensures that values passed to our model constructor that were not specified in our schema do not get saved to the db.
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
1
This also affects the use of
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
82 to set a property value.
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
2
This value can be overridden at the model instance level by passing a second boolean argument:
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
3
The
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
83 option may also be set to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
84 which will cause errors to be produced instead of dropping the bad data.
NOTE: Any key/val set on the instance that does not exist in your schema is always ignored, regardless of schema option.
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
4
Mongoose supports a separate
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
85 option to avoid strict mode for query filters. This is because empty query filters cause Mongoose to return all documents in the model, which can cause issues.
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
5
The
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
83 option does apply to updates. The
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
85 option is just for query filters.
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
6
Mongoose has a separate
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
85 option to toggle strict mode for the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
89 parameter to queries.
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
7
In general, we do not recommend passing user-defined objects as query filters:
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
8
In Mongoose 7,
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
85 is
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
16 by default. However, you can override this behavior globally:
const schema = new Schema[{ _id: Number }];
const Model = mongoose.model['Test', schema];
const doc = new Model[];
await doc.save[]; // Throws "document must have an _id before saving"
doc._id = 1;
await doc.save[]; // works
9
Exactly the same as the option but only applies when the document's
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
92 method is called.
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
0
To see all available
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
93 options, read .
Documents have a method which converts the mongoose document into a plain JavaScript object. This method accepts a few options. Instead of applying these options on a per-document basis, we may declare the options at the schema level and have them applied to all of the schema's documents by default.
To have all virtuals show up in your
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
94 output, set the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
95 option to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
96:
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
1
To see all available
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
95 options, read .
By default, if you have an object with key 'type' in your schema, mongoose will interpret it as a type declaration.
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
2
However, for applications like geoJSON, the 'type' property is important. If you want to control which key mongoose uses to find type declarations, set the 'typeKey' schema option.
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
3
By default, documents are automatically validated before they are saved to the database. This is to prevent saving an invalid document. If you want to handle validation manually, and be able to save objects which don't pass validation, you can set
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
98 to false.
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
4
The
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
99 is a property set on each document when first created by Mongoose. This keys value contains the internal revision of the document. The
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
99 option is a string that represents the path to use for versioning. The default is
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
01. If this conflicts with your application you can configure as such:
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
5
Note that Mongoose's default versioning is not a full optimistic concurrency solution. Mongoose's default versioning only operates on arrays as shown below.
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
6
If you need optimistic concurrency support for
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
02, you can set the
Document versioning can also be disabled by setting the
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
99 to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
16. DO NOT disable versioning unless you know what you are doing.
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
7
Mongoose only updates the version key when you use . If you use
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
07,
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
08, etc. Mongoose will not update the version key. As a workaround, you can use the below middleware.
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
8
Optimistic concurrency is a strategy to ensure the document you're updating didn't change between when you loaded it using
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
09 or
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
10, and when you update it using
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
02.
For example, suppose you have a
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
12 model that contains a list of
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
13, and a
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
14 that represents whether this house shows up in searches. Suppose that a house that has status
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
15 must have at least two
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
13. You might implement the logic of approving a house document as shown below:
// define a schema
const animalSchema = new 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];
}
}
}];
// Or, assign a function to the "methods" object of our animalSchema
animalSchema.methods.findSimilarTypes = function[cb] {
return mongoose.model['Animal'].find[{ type: this.type }, cb];
};
9
The
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
17 function looks right in isolation, but there might be a potential issue: what if another function removes the house's photos between the
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
10 call and the
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
02 call? For example, the below code will succeed:
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
0
If you set the
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
03 option on the
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
12 model's schema, the above script will throw an error.
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
1
Sets a default collation for every query and aggregation. Here's a beginner-friendly overview of collations.
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
2
If you set the
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
22 option on a schema, Mongoose will create a timeseries collection for any model that you create from that schema.
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
3
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
23 allows excluding paths from versioning [i.e., the internal revision will not be incremented even if these paths are updated]. DO NOT do this unless you know what you're doing. For subdocuments, include this on the parent document using the fully qualified path.
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
4
The
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
24 option tells Mongoose to assign
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
25 and
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
26 fields to your schema. The type assigned is .
By default, the names of the fields are
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
25 and
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
26. Customize the field names by setting
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
29 and
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
30.
The way
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
24 works under the hood is:
- If you create a new document, mongoose simply sets
const schema = new Schema[]; schema.path['_id']; // ObjectId { ... }
25, and
26 to the time of creation.const schema = new Schema[]; schema.path['_id']; // ObjectId { ... }
- If you update a document, mongoose will add
const schema = new Schema[]; schema.path['_id']; // ObjectId { ... }
26 to the
35 object.const schema = new Schema[]; schema.path['_id']; // ObjectId { ... }
- If you set
const schema = new Schema[]; schema.path['_id']; // ObjectId { ... }
36 on an update operation, mongoose will use
const schema = new Schema[]; schema.path['_id']; // ObjectId { ... }
37 operator to add
const schema = new Schema[]; schema.path['_id']; // ObjectId { ... }
25 to the document in case the
39 operation resulted into a new inserted document.const schema = new Schema[]; schema.path['_id']; // ObjectId { ... }
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
5
By default, Mongoose uses
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
40 to get the current time. If you want to overwrite the function Mongoose uses to get the current time, you can set the
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
41 option. Mongoose will call the
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
41 function whenever it needs to get the current time.
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
6
Mongoose supports defining global plugins, plugins that apply to all schemas.
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
7
Sometimes, you may only want to apply a given plugin to some schemas. In that case, you can add
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
43 to a schema:
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
8
If you call
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
44 with a
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
45 option, Mongoose will only apply that plugin to schemas that have a matching entry in
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
43.
const Animal = mongoose.model['Animal', animalSchema];
const dog = new Animal[{ type: 'dog' }];
dog.findSimilarTypes[[err, dogs] => {
console.log[dogs]; // woof
}];
9
By default, Mongoose will automatically
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
47 any populated paths for you, unless you explicitly exclude them.
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
0
To opt out of selecting populated fields by default, set
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
48 to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
16 in your schema.
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
1
For legacy reasons, when there is a validation error in subpath of a single nested schema, Mongoose will record that there was a validation error in the single nested schema path as well. For example:
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
2
Set the
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
50 to
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
16 on the child schema to make Mongoose only reports the parent error.
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
3
Options like and affect the options Mongoose passes to MongoDB when creating a new collection. Mongoose schemas support most MongoDB
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
47 options, but not all. You can use the
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
55 option to set any
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
47 options; Mongoose will use
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
55 as the default values when calling
const Blog = mongoose.model['Blog', blogSchema];
// ready to go!
47 for your schema.
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
4
Schemas have a that you can use to create a Mongoose schema from an ES6 class:
- become
- become
- become Mongoose virtuals
Here's an example of using
const schema = new Schema[];
schema.path['_id']; // ObjectId { ... }
59 to create a schema from an ES6 class:
// define a schema
const animalSchema = new Schema[{ name: String, type: String },
{
// Assign a function to the "statics" 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 statics functions.
statics: {
findByName[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
}
}
}];
// Or, Assign a function to the "statics" object of our animalSchema
animalSchema.statics.findByName = function[name] {
return this.find[{ name: new RegExp[name, 'i'] }];
};
// Or, equivalently, you can call `animalSchema.static[]`.
animalSchema.static['findByBreed', function[breed] { return this.find[{ breed }]; }];
const Animal = mongoose.model['Animal', animalSchema];
let animals = await Animal.findByName['fido'];
animals = animals.concat[await Animal.findByBreed['Poodle']];
5
Schemas are also pluggable which allows us to package up reusable features into plugins that can be shared with the community or just between your projects.
Here's an alternative introduction to Mongoose schemas.
To get the most out of MongoDB, you need to learn the basics of MongoDB schema design. SQL schema design [third normal form] was designed to minimize storage costs, whereas MongoDB schema design is about making common queries as fast as possible. The 6 Rules of Thumb for MongoDB Schema Design blog series is an excellent resource for learning the basic rules for making your queries fast.
Users looking to master MongoDB schema design in Node.js should look into The Little MongoDB Schema Design Book by Christian Kvalheim, the original author of the MongoDB Node.js driver. This book shows you how to implement performant schemas for a laundry list of use cases, including e-commerce, wikis, and appointment bookings.