Learn Mongoose
Tags: mongoose, mongodb
Published: 2021-12-30 18:29:18

Mongoose is like a wrapper around MongoDB.

With mongoose we do not need to wait to get mongoDB connected. Mongoose will queue up all the command you make and only make those command after it connect to mongoDB .

for mongoose you need to know 3 basic concept.

Inside mongoose, there are 3 main concepts we need to understand first

1. schema - it defines , what the structure of your data look like. 
2. Model - It is the actual form of a schema. A model is a class with which we construct documents.
3. Query - A query is just a query we make against mongoDB database.

we can write all schema in one file. But it is good to use different file for each schema.

Schema takes an object with key value pairs , where key is the name of the key in your mongoDB object. so if we want the user have a name , we give it a key of a name. And then the value will be the datatype of ***name** ,* that is ***String***.

```jsx
const mongoose = require('mongoose')

const userSchema = new mongoose.Schema({
    name: String,
    age : Number
})
```

We now have a user schema that defines a name field and a age field. And the name going to be a string and age is going to be a number.

Now we have to create a model for this schema. we have to user *mongoose.model()* function for this.  This function takes a name of the model, in our case, this is going to ‘User’’. And we have to pass a schema as the second parameter.

```jsx
mongoose.model('User', userSchema)
```

If we create the schema in another file, we have to export the model.

```jsx
module.exports=  mongoose.model('User', userSchema)
```

**Now, let’s create a user**.

As we created the schema in another file , we have to require it on the main script.

```jsx
const User = require('./user');
```

we can create user by instantiate User class as new user object and pass a object.

```jsx
new User({ name: 'abir', age: 6 })
```

It just create a local copy of a user in our script. it won’t save to database. We have to use save() function for this.

[ It give use a promise. But it is more cleaner to use ***async await*** instant of promise. ]\

```jsx
run();
async function run() {
    const user = await new User({ name: 'abir', age: 6 })
    await user.save();
    console.log(user);
		//return
		// {
		//    name: 'abir',
    //    age: 6,
    //    _id: new ObjectId("61ccb948e35a787b6ad2b812"),
    //    __v: 0
    // }
}
```

We can also create a user using the create() method on the actual ***User*** class.

```jsx
run();
async function run() {
    const user = await User.create({ name: 'abir', age: 21 })
    console.log(user)
}
```

### Schema type

we can use many types like String, Number, Date , ObjectId etc.

We can use nested object in schema like what we did for ***address —***—

```jsx
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    name: String,
    age: Number,
    cratedAt: Date,
    updatedAt: Date,
    bestFriend: mongoose.SchemaTypes.ObjectId,
    hobbies: [String],
    address: {
        street: String,
        city: String,
    }
});

module.exports = mongoose.model('User', userSchema);
```

We can create whole asperated schema for “**address”** like this 

```jsx
const addressSchema = new mongoose.Schema({
    street: String,
    city: String,
});

const userSchema = new mongoose.Schema({
    name: String,
    age: Number,
    cratedAt: Date,
    updatedAt: Date,
    bestFriend: mongoose.SchemaTypes.ObjectId,
    hobbies: [String],
    address: addressSchema,
});
```

This is much useful for complex schema.

### Validation——————————

We should use try catch for error handling

```jsx
const mongoose = require('mongoose');
const User = require('./user');

mongoose.connect('mongodb://localhost/test', () => {
    console.log('connected');
})

run();
async function run() {
    try {

        const user = await User.create({
            name: 'abir',
            age: 'ab'
        })
        user.name = 'rafi'
        user.save();
        console.log(user)
    } catch (e) {
        console.log(e.message)
    }

}
```

 

we can add additional properties to field in our schema in object format.

we can set a field “*require*” in a schema like this—

```jsx
const userSchema = new mongoose.Schema({
    name: String,
    email:{
        type: String,
        required: true,
    },
    age: Number,
});
```

some additional properties we can use in our schema-

1. required - it is like require attribute of html form . That’s means we must include the filed
2. lowercase - it will automatically convert the given email to lowercase.
3. uppercase - it will automatically convert the given email to uppercase.  
4. default - set a default value.
5. immutable - make a field immutable or unchangeable.