Introduction to Mongoose Foundation

Keywords: Javascript Mongoose MongoDB Database npm

Previous remarks

Mongoose is an object model tool that can operate mongodb conveniently under node.js asynchronous environment. This article describes in detail how to use Mongoose to operate MongoDB

 

NodeJS Driver

Before introducing Mongoose, I first introduce how to operate MongoDB using NodeJS

If you use a program to operate a database, you need to use the MongoDB driver. MongoDB driver is actually an interface for applications. Different languages correspond to different drivers. NodeJS driver can not be used in other back-end languages.

First, install mongodb

npm install mongodb

Next, use require() method to introduce mongodb database; then use connect() method of MongoClient object to connect mongodb; finally, use node to check mongodb asynchronously.

Establish db1 database in mongodb database, then create col collection by following code, and insert {"a":1} document

var mongodb = require('mongodb');
mongodb.MongoClient.connect("mongodb://localhost/db1",function(err,db){
    if(!err){
        db.collection("col").insert({"a":1},function(err,result){
            if(!err){
                console.log(result);
            }
        })
    }
})

The final results are as follows.

{ result: { ok: 1, n: 1 },
  ops: [ { a: 1, _id: 597077dc271d092728caa362 } ],
  insertedCount: 1,
  insertedIds: [ 597077dc271d092728caa362 ] }

 

Summary

Mongoose is the driver of NodeJS and cannot be used as the driver of other languages. Mongoose has two characteristics

1. Designing non-relational database through the idea of relational database

2. Simplify operation based on mongodb driver

There are three important concepts in Mongooose: Schema, Model and Entity. Their relationship is: Schema generates model, Model creates Document, Model and Document can affect database operations, but Model is more operational than Document.

Schema is used to define the structure of the database. Similar to the data definition when creating tables (not only the structure and attributes of documents can be defined, but also the instance method, static model method, composite index of documents can be defined). Each Schema maps to a collection in mongodb. Schema does not have the ability to operate the database.

Model is a constructor compiled by Schema, which has abstract attributes and behaviors, and can add, delete and modify databases. Each instance of Model is a document document.

Document is an entity created by Model, and its operation also affects the database.

 

install

Installation nodejs and mongodb After that, use npm to install mongoose

npm install mongoose

Once the installation is successful, you can use it through require('mongoose').

 

Connect to the database

After you include mongoose in your project using the require() method, connect to the MongoDB database using the connect() method

[connect()]

mongoose.connect(url);

The simplest way to use connect() is to simply pass in the url parameter, as shown below. Connect to the db1 server of the local localhost

mongoose.connect('mongodb://localhost/db1');

If you also need to pass the username and password, you can use the following method

mongoose.connect('mongodb://username:password@host:port/database?options...');

The connect() method also accepts an option object options, which is passed to the underlying driver. All options included here take precedence over those passed in connection strings

mongoose.connect(uri, options);

The available options are as follows

 db            -Database Settings
 server        -server setting
 replset       -Duplicate Set Settings
 user          -User name
 pass          -Password
 auth          -Authentication options
 mongos        -Connecting multiple databases
 promiseLibrary
var options = {
  db: { native_parser: true },
  server: { poolSize: 5 },
  replset: { rs_name: 'myReplicaSetName' },
  user: 'myUserName',
  pass: 'myPassword'
}
mongoose.connect(uri, options);

If you want to connect to multiple databases, you only need to set up multiple URLs to separate them and set mongos to true

mongoose.connect('urlA,urlB,...', {
   mongos : true 
})

The connect() function also accepts a callback parameter

mongoose.connect(uri, options, function(error) {

});

After executing the following code, the console output "Connect Successfully"

var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/test", function(err) {
    if(err){
        console.log('connection failed');
    }else{
        console.log('Successful connection');
    }
});

If the authentication control is turned on, login to the'db1'database with the username "u1" and password "123456". After executing the code, the console output "Connect Successfully"

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(err){
        console.log('connection failed');
    }else{
        console.log('Successful connection');
    }
});

[disconnect()] 

mongoose.disconnect()

disconnect() method to disconnect

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(err){
        console.log('connection failed');
    }else{
        console.log('Successful connection');
    }
});
setTimeout(function(){
    mongoose.disconnect(function(){
        console.log("Disconnect");
    })
}, 2000);

 

Schema

Schema is mainly used to define the structure of document document in Collection collection in MongoDB.

Defining Schema is very simple, specifying field names and types, and supporting eight types

String string
Number number    
Date date
Buffer binary
Boolean Boolean Value
Mixed type
ObjectId object ID    
Array array

Call Schema through mongoose.Schema, and then use the new method to create schema objects

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var mySchema = new Schema({
  title:  String,
  author: String,
  body:   String,
  comments: [{ body: String, date: Date }],
  date: { type: Date, default: Date.now },
  hidden: Boolean,
  meta: {
    votes: Number,
    favs:  Number
  }
});

[Note] When creating a Schema object, there are two ways to declare the field type, one is the field type with capital initials, and the other is the type of lower-case segment with quotation marks.

var mySchema = new Schema({title:String, author:String});
//perhaps 
var mySchema = new Schema({title:'string', author:'string'});

If you need to add other fields after the Schema definition, you can use the add() method

var MySchema = new Schema;
MySchema.add({ name: 'string', color: 'string', price: 'number' });

  

Model

Model Models are constructors compiled from Schema, or classes, through which document objects can be instantiated.

The creation and retrieval of document documents need to be handled through Model model

[model()]

mongoose.model()

Schema is compiled into Model using the model() method. The first parameter of the model() method is the model name.

[Note] Be sure to set the first parameter of the model() method and its return value to the same value, otherwise unpredictable results will occur.

Mongoose sets the collection name to a lowercase version of the model name. If the last character of the name is a letter, it becomes plural; if the last character of the name is a number, it does not change; if the model name is "MyModel", the collection name is "mymodels"; if the model name is "Model 1", the collection name is "Model 1".

var schema = new mongoose.Schema({ num:Number, name: String, size: String});
var MyModel = mongoose.model('MyModel', schema);

[instantiated document]

The document document document object is instantiated by using the new method in prototype Model1

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(err){
        console.log('connection failed');
    }else{
        console.log('Successful connection');
        var schema = new mongoose.Schema({ num:Number, name: String, size: String});
        var MyModel = mongoose.model('MyModel', schema);
        var doc1 = new MyModel({ size: 'small' });
        console.log(doc1.size);//'small'
    }
});

[Document Preservation]

Document doc1 created by new Model1() must be saved () to save the created document into the database collection, which is a plural lowercase version of the model name.

The callback function is optional. The first parameter is err and the second parameter is the saved document object.

save(function (err, doc) {})
var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ num:Number, name: String, size: String });
        var MyModel = mongoose.model('MyModel', schema);
        var doc1 = new MyModel({ size: 'small' });
        doc1.save(function (err,doc) {
        //{ __v: 0, size: 'small', _id: 5970daba61162662b45a24a1 }
          console.log(doc);
        })
    }
});

As shown in the figure below, the collection name in the db1 database is mymodels, and there is a {size:"small"} document in it.

 

Custom Method

[Example Method]

The example of Model is document. There are many built-in instance methods, such as save. The method attribute of Schema object can be used to customize the extended method for instance.

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ num:Number, name: String, size: String });        
        schema.methods.findSimilarSizes = function(cb){
            return this.model('MyModel').find({size:this.size},cb);
        }
        var MyModel = mongoose.model('MyModel', schema);
        var doc1 = new MyModel({ name:'doc1', size: 'small' });
        var doc2 = new MyModel({ name:'doc2', size: 'small' });
        var doc3 = new MyModel({ name:'doc3', size: 'big' });
        doc1.save();
        doc2.save();
        doc3.save();
        setTimeout(function(){
            doc1.findSimilarSizes(function(err,docs){
                docs.forEach(function(item,index,arr){
                    //doc1
                    //doc2
                     console.log(item.name)        
                })
            })  
        },0)  
    }
});

[Static method]

Adding static methods to the Model through the static properties of the Schema object

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ num:Number, name: String, size: String });        
        schema.statics.findByName = function(name,cb){
            return this.find({name: new RegExp(name,'i')},cb);
        }
        var MyModel = mongoose.model('MyModel', schema);
        var doc1 = new MyModel({ name:'doc1', size: 'small' });
        var doc2 = new MyModel({ name:'doc2', size: 'small' });
        var doc3 = new MyModel({ name:'doc3', size: 'big' });
        doc1.save();
        doc2.save();
        doc3.save();
        setTimeout(function(){
            MyModel.findByName('doc1',function(err,docs){
                //[ { _id: 5971e68f4f4216605880dca2,name: 'doc1',size: 'small',__v: 0 } ]
                console.log(docs);
            })  
        },0)  
    }
});

As shown above, the difference between the instance method and the static method is that the static method adds a method to the model through the static attribute of the Schema object, and the instance method adds a method to the document through the method of the Schema object.

[Query Method]

Add query method to model by query attribute of schema object

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ age:Number, name: String});        
        schema.query.byName = function(name){
            return this.find({name: new RegExp(name)});
        }
        var temp = mongoose.model('temp', schema);   
        temp.find().byName('huo').exec(function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },
            // { _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 } ]
            console.log(docs);
        })  

    }           
});

 

Document Added

There are three new ways to add documents. One is to use the save() method of the document described above, the other is to use the create() method of the model model, and the last is the insertMany() method of the model.

[save()]

[Note] Callback functions can be omitted

save([options], [options.safe], [options.validateBeforeSave], [fn])

Create a new {age:10,name:'save'} document and save it

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ age:Number, name: String});        
        var temp = mongoose.model('temp', schema);
        //Using Chain Writing    
        new temp({age:10,name:'save'}).save(function(err,doc){
            //[ { _id: 59720bc0d2b1125cbcd60b3f, age: 10, name: 'save', __v: 0 } ]
            console.log(doc);        
        });         
    }           
});

[create()]

Using the save() method, you need to instantiate the document first, and then use the save() method to save the document. The create() method operates directly on the Model model and can add multiple documents at the same time.

Model.create(doc(s), [callback])

Add {name:"xiaowang"}, {name:"xiaoli"} these two documents

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ age:Number, name: String});        
        var temp = mongoose.model('temp', schema);   
        temp.create({name:"xiaowang"},{name:"xiaoli"},function(err,doc1,doc2){
            //{ __v: 0, name: 'xiaowang', _id: 59720d83ad8a953f5cd04664 }
            console.log(doc1); 
            //{ __v: 0, name: 'xiaoli', _id: 59720d83ad8a953f5cd04665 }
            console.log(doc2); 
        });       
    }           
});

[insertMany()]

Model.insertMany(doc(s), [options], [callback])

Add {name:"a"}, {name:"b"} these two documents

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ age:Number, name: String});        
        var temp = mongoose.model('temp', schema);   
        temp.insertMany([{name:"a"},{name:"b"}],function(err,docs){
            //[ { __v: 0, name: 'a', _id: 59720ea1bbf5792af824b30c },
            //{ __v: 0, name: 'b', _id: 59720ea1bbf5792af824b30d } ]
            console.log(docs); 
        });       

    }           
});

  

Document query

It's easy to use Mongoose to find documents. There are three ways to choose from

find()
findById()
findOne()

[find()]

The first parameter represents the query condition, the second parameter controls the field returned, the third parameter configures the query parameter, the fourth parameter is the callback function, and the form of the callback function is function(err,docs) {}

Model.find(conditions, [projection], [options], [callback])

The following data exists in the collection temps of database db1

Now, use the find() method to find all the data

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ age:Number, name: String});        
        var temp = mongoose.model('temp', schema);
        temp.find(function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },
            //{ _id: 5971f93be6f98ec60e3dc86d, name: 'wang', age: 18 },
            //{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 },
            //{ _id: 5971f93be6f98ec60e3dc86f, name: 'li', age: 12 } ]
            console.log(docs);
        })
    }
});

Find data older than 18

        temp.find({age:{$gte:18}},function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },
            //{ _id: 5971f93be6f98ec60e3dc86d, name: 'wang', age: 18 },
            //{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 }]
            console.log(docs);
        })

Find data that are older than 18 and have'huo'in their names

        temp.find({name:/huo/,age:{$gte:18}},function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },
            //{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 }]
            console.log(docs);
        })

Find the data with'a'in the name and output only the'name' field.

[Note]_id field default output

        temp.find({name:/a/},'name',function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai' },
            //{ _id: 5971f93be6f98ec60e3dc86d, name: 'wang' } ]
            console.log(docs);
        })

If you really don't need the output of the _id field, you can do the following settings

        temp.find({name:/a/},{name:1,_id:0},function(err,docs){
            //[ { name: 'huochai' }, { name: 'wang' } ]
            console.log(docs);
        })

Find all other data that skips the first two data

[Note] If the third parameter is used, the first two parameters need to be set to null if they have no values

        temp.find(null,null,{skip:2},function(err,docs){
            //[ { _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 },
            //{ _id: 5971f93be6f98ec60e3dc86f, name: 'li', age: 12 } ]
            console.log(docs);
        })

[findById()]

Model.findById(id, [projection], [options], [callback])

Display all fields of element 0

        var aIDArr = [];
        temp.find(function(err,docs){
            docs.forEach(function(item,index,arr){
                aIDArr.push(item._id);
            })
            temp.findById(aIDArr[0],function(err,doc){
                //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }
                console.log(doc);
            })            
        })

Another way to write the above code is as follows

        var aIDArr = [];
        temp.find(function(err,docs){
            docs.forEach(function(item,index,arr){
                aIDArr.push(item._id);
            })
            temp.findById(aIDArr[0]).exec(function(err,doc){
                //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }
                console.log(doc);
            })            
        })

Output only the name field

            temp.findById(aIDArr[0],{name:1,_id:0},function(err,doc){
                //{  name: 'huochai'}
                console.log(doc);
            })            

Or in the following form

            temp.findById(aIDArr[0],{name:1,_id:0}).exec(function(err,doc){
                //{  name: 'huochai'}
                console.log(doc);
            })            

Minimum field output

            temp.findById(aIDArr[0],{lean:true},function(err,doc){
                //{ _id: 5971f93be6f98ec60e3dc86c }
                console.log(doc);
            })   
            temp.findById(aIDArr[0],{lean:true}).exec(function(err,doc){
                //{ _id: 5971f93be6f98ec60e3dc86c }
                console.log(doc);
            })     

[findOne()]

This method returns the first of all instances found

Model.findOne([conditions], [projection], [options], [callback])

Find the first document in the age > 20 document

temp.findOne({age:{$gt : 20}},function(err,doc){
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }
    console.log(doc);
})   
temp.findOne({age:{$gt : 20}}).exec(function(err,doc){
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }
    console.log(doc);
})  

Find the first document in the age > 20 document and output only the name field

temp.findOne({age:{$gt : 20}},{name:1,_id:0},function(err,doc){
    //{ name: 'huochai' }
    console.log(doc);
})   
temp.findOne({age:{$gt : 20}},{name:1,_id:0}).exec(function(err,doc){
    //{ name: 'huochai' }
    console.log(doc);
})     

Find the first document in the age > 20 document and output the shortest field including the name field

temp.findOne({age:{$gt : 20}},"name",{lean:true},function(err,doc){
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai' }
    console.log(doc);
})   
temp.findOne({age:{$gt : 20}},"name").lean().exec(function(err,doc){
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai' }
    console.log(doc);
})   

In document query, the common query conditions are as follows

or relationship
Or negativity
$gt >
More than or equal to $gte
Less than $lt
Less than or equal to
Not equal to $ne
$in) Within a range of values
$nin) Not in multiple values
Match multiple values in an array
$regex regular for fuzzy queries
Matching array size
maxDistance range query, distance (based on LBS)
Modular operation
near. Neighborhood query, query the location nearby (based on LBS)
Does the $exists field exist?
$elemMatch matches elements in the inner array
within scope query (based on LBS)
Range query, rectangular range (based on LBS)
Range alert, $center, circular range (based on LBS)
Center Sphere range query, spherical range (based on LBS)
Inquiry for elements in the field set (e.g. from the number after, N to M first elements)

[$where]

For more complex queries, you need to use the $where operator, which is powerful and flexible and can use arbitrary JavaScript as part of the query, including strings of JavaScript expressions or JavaScript functions.

Using strings

temp.find({$where:"this.x == this.y"},function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]
    console.log(docs);
}) 
temp.find({$where:"obj.x == obj.y"},function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]
    console.log(docs);
}) 

Using functions

temp.find({$where:function(){
        return obj.x !== obj.y;
    }},function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },
    //{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 } ]
    console.log(docs);
}) 
temp.find({$where:function(){
        return this.x !== this.y;
    }},function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },
    //{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 } ]
    console.log(docs);
}) 

 

Document Update

Document updates can be done in the following ways

update()
updateMany()
find() + save() updateOne()
findOne() + save() findByIdAndUpdate() fingOneAndUpdate()

 [update()]

The first parameter condition is the query condition, the second parameter doc is the data to be modified, the third parameter options is the control option, and the fourth parameter is the callback function.

Model.update(conditions, doc, [options], [callback])

Options have the following options

   safe (boolean): Default to true. Safety mode.
upsert (boolean): defaults to false. Create a new record if it does not exist.
multi (boolean): The default is false. Whether to update multiple query records.
runValidators: If the value is true, perform Validation validation.
SetDefaults On Insert: If the upsert option is true, insert the default value of the document definition at new build time.
strict (boolean): Update in string mode.
overwrite (boolean): The default is false. Disable update-only mode to allow overwriting of records.

Existing data in database temps are as follows

Now use update() to query data older than 20 and change its age to 40

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ age:Number, name: String});        
        var temp = mongoose.model('temp', schema);   
        temp.update({age:{$gte:20}},{age:40},function(err,raw){
            //{ n: 1, nModified: 1, ok: 1 }
            console.log(raw);
        })

    }           
});

After the above operations, the database results are as follows. Only the first data was changed to 40 years old. The third data did not change.

If you want to update multiple records at the same time, you need to set multi in options to true. Let's set the age of the'a'character in the name to 10.

var mongoose = require('mongoose');
mongoose.connect("mongodb://u1:123456@localhost/db1", function(err) {
    if(!err){
        var schema = new mongoose.Schema({ age:Number, name: String});        
        var temp = mongoose.model('temp', schema);   
        temp.update({name:/a/},{age: 10},{multi:true},function(err,raw){
            //{ n: 2, nModified: 2, ok: 1 }
            console.log(raw);
        })

    }           
});

If the search conditions are set, the data in the database is not satisfied and nothing happens by default.

temp.update({age:100},{name: "hundred"},function(err,raw){
    //{ n: 0, nModified: 0, ok: 1 }
    console.log(raw);
})

If the upsert parameter in options is set to true, and if there is no document that meets the query criteria, mongo will insert a new document into the collection by synthesizing the first and second parameters

temp.update({age:100},{name: "hundred"},{upsert:true},function(err,raw){
    //{ n: 1, nModified: 0,upserted: [ { index: 0, _id: 5972c202d46b621fca7fc8c7 } ], ok: 1 }
    console.log(raw);
})
temp.update({name:/aa/},{age: 0},{upsert:true},function(err,raw){
    //{ n: 1, nModified: 0,upserted: [ { index: 0, _id: 5972c288d46b621fca7fdd8f } ], ok: 1 }
    console.log(raw);
})

[Note] The callback function in the update() method cannot be omitted, otherwise the data will not be updated. If there is no useful information in the callback function, you can use exec() to simplify the code

temp.update({name:/aa/},{age: 0},{upsert:true}).exec();

[updateMany()]

The only difference between updateMany() and update() methods is that multiple documents are updated by default, and even setting {multi:false} cannot update only the first document.

Model.updateMany(conditions, doc, [options], [callback])

Change the database's name to'huo'and age to 50

temp.updateMany({name:/huo/},{age:50},function(err,raw){
    //{ n: 2, nModified: 2, ok: 1 }
    console.log(raw);
});

[find() + save()]

If the operation that needs to be updated is more complicated, you can use find()+save() method to process, such as finding data younger than 30 years old, adding the'30'character after the name.

temp.find({age:{$lt:20}},function(err,docs){
    //[ { _id: 5971f93be6f98ec60e3dc86d, name: 'wang', age: 10 },
    //{ _id: 5971f93be6f98ec60e3dc86f, name: 'li', age: 12 }]
    console.log(docs);
    docs.forEach(function(item,index,arr){
        item.name += '30';
        item.save();
    })
    //[ { _id: 5971f93be6f98ec60e3dc86d, name: 'wang30', age: 10 },
    // { _id: 5971f93be6f98ec60e3dc86f, name: 'li30', age: 12 }]
    console.log(docs);
});

[updateOne()]

The updateOne() method can only update the first data found, and even setting {multi:true} cannot update multiple documents at the same time.

Change the database's name to'huo'and age to 60

temp.updateOne({name:/huo/},{age:60},function(err,raw){
    //{ n: 1, nModified: 1, ok: 1 }
    console.log(raw);
});

[findOne() + save()]

If the operation that needs to be updated is complex, you can use findOne()+save() method to process, such as finding data named'huochai', aged 100 years.

temp.findOne({name:'huochai'},function(err,doc){
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 10 }
    console.log(doc);
    doc.age += 100;
    doc.save();
    //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 110 }
    console.log(doc);
});

[findOneAndUpdate()]

The fourth parameter callback function of the fineOneAndUpdate() method takes the form of function(err,doc) {}

Model.findOneAndUpdate([conditions], [update], [options], [callback])

[findByIdAndUpdate]

The fourth parameter callback function of fineByIdAndUpdate() method takes the form of function(err,doc) {}

Model.findOneAndUpdate([conditions], [update], [options], [callback])

 

documents deleting

There are three ways to delete documents

remove()
findOneAndRemove()
findByIdAndRemove()

[remove()]

There are two forms of remove, one is the remove() method of the document and the other is the remove() method of the Model.

Next, the remove() method of Model is introduced. The first parameter condition of the method is the query condition, and the second parameter callback function is in the form of function(err) {}.

model.remove(conditions, [callback])

Delete data whose name includes'30'in the database

temp.remove({name:/30/},function(err){})

[Note] The callback function in the remove() method cannot be omitted, otherwise the data will not be deleted. Of course, you can use the exec() method to abbreviate code

temp.remove({name:/30/}).exec()

The document's remove() method is described below. The parameter callback function of this method is in the form of function(err,doc) {}

document.remove([callback])

Delete data whose name contains'huo'in the database

[Note] The callback function parameters of the remove() method of the document can be omitted

temp.find({name:/huo/},function(err,doc){
    doc.forEach(function(item,index,arr){
        item.remove(function(err,doc){
            //{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 30 }
            //{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 60 }
            console.log(doc);
        })
    })
})  

[findOneAndRemove()]

The remove() of the model deletes all eligible data. If only the first eligible data is deleted, the findOne AndRemove () method of the model can be used.

Model.findOneAndRemove(conditions, [options], [callback])

Collecting temps available data is as follows

Now delete the first data under 20

temp.findOneAndRemove({age:{$lt:20}},function(err,doc){
    //{ _id: 5972d3f3e6f98ec60e3dc873, name: 'wang', age: 18 }
    console.log(doc);
})

The callback function cannot be omitted, as in the remove() method of the model, otherwise the data will not be deleted. Of course, you can use the exec() method to abbreviate code

temp.findOneAndRemove({age:{$lt:20}}).exec()

[findByIdAndRemove()]

Model.findByIdAndRemove(id, [options], [callback])

Delete element 0

var aIDArr = [];
temp.find(function(err,docs){
    docs.forEach(function(item,index,arr){
        aIDArr.push(item._id);
    })
    temp.findByIdAndRemove(aIDArr[0],function(err,doc){
        //{ _id: 5972d754e6f98ec60e3dc882, name: 'huochai', age: 27 }
        console.log(doc);
    })            
})

Similarly, the callback function cannot be omitted in this method, otherwise the data will not be deleted. Of course, you can use the exec() method to abbreviate code

var aIDArr = [];
temp.find(function(err,docs){
    docs.forEach(function(item,index,arr){
        aIDArr.push(item._id);
    })
    temp.findByIdAndRemove(aIDArr[0]).exec()            
})

 

Front and back hooks

Back and forth hooks are pre() and post() methods, also known as middleware, which are functions that can be executed when performing certain operations. Middleware is specified on schema, similar to static or instance methods, etc.

The front and back hooks can be set when the following operations are performed in the database

    init
    validate
    save
    remove
    count
    find
    findOne
    findOneAndRemove
    findOneAndUpdate
    insertMany
    update

[pre()]

Take the find() method as an example, execute the pre() method before executing the find() method

var schema = new mongoose.Schema({ age:Number, name: String,x:Number,y:Number});  
schema.pre('find',function(next){
    console.log('I am pre Method 1');
    next();
});
schema.pre('find',function(next){
    console.log('I am pre Method 2');
    next();
});  
var temp = mongoose.model('temp', schema);
temp.find(function(err,docs){
    console.log(docs[0]);
})    
/*
I'm pre Method 1
I'm pre Method 2
{ _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 }
*/

[post()]

The post() method is not a method to execute after performing certain operations, but a method to execute last before performing certain operations, which can not be used in the post() method.

var schema = new mongoose.Schema({ age:Number, name: String,x:Number,y:Number});  
schema.post('find',function(docs){
    console.log('I am post Method 1');
});
schema.post('find',function(docs){
    console.log('I am post Method 2');
});
var temp = mongoose.model('temp', schema);
temp.find(function(err,docs){
    console.log(docs[0]);
}) 
/*
I'm post method 1
I'm post method 2
{ _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 }
 */   

 

Query post-processing

Commonly used post-processing methods for queries are as follows

Sort sort sort
Skp skip limit restriction select display field exect execution
Count count
distinct de-weighting
var schema = new mongoose.Schema({ age:Number, name: String,x:Number,y:Number});  
var temp = mongoose.model('temp', schema);
temp.find(function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },
    //{ _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]
    console.log(docs);
}) 

[sort()]

Sort by age from small to large

temp.find().sort("age").exec(function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 },
    //{ _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },
    //{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 } ]
    console.log(docs);
}); 

Arrange age from big to small according to x

temp.find().sort("x -age").exec(function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },
    //{  _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]
    console.log(docs);
}); 

[skip()]

Skip 1 to show the others

temp.find().skip(1).exec(function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 },
    //{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]
    console.log(docs);
}); 

[limit()]

Display 2

temp.find().limit(2).exec(function(err,docs){
    //[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },
    //{ _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 } ]
    console.log(docs);
}); 

[select()]

Display name, age fields, not _id fields

temp.find().select("name age -_id").exec(function(err,docs){
    //[ { name: 'huochai', age: 27 },{ name: 'wang', age: 18 },{ name: 'huo', age: 30 },{ name: 'li', age: 20 } ]
    console.log(docs);
}); 
temp.find().select({name:1, age:1, _id:0}).exec(function(err,docs){
    //[ { name: 'huochai', age: 27 },{ name: 'wang', age: 18 },{ name: 'huo', age: 30 },{ name: 'li', age: 20 } ]
    console.log(docs);
}); 

Next, we will combine the above methods. After skipping the first one, only two data will be displayed, sorted by age from large to small, and the _id field will not be displayed.

temp.find().skip(1).limit(2).sort("-age").select("-_id").exec(function(err,docs){
    //[ { name: 'huochai', age: 27, x: 1, y: 2 },
    //{ name: 'li', age: 20, x: 2, y: 2 } ]
    console.log(docs);
}); 

[count()]

Display the number of documents in the collection temps

temp.find().count(function(err,count){
    console.log(count);//4
}); 

[distinct()]

Returns the value of x in the set temps

temp.find().distinct('x',function(err,distinct){
    console.log(distinct);//[ 1, 2 ]
}); 

 

Document validation

Why do you need document validation? As an example, schema defines the following

var schema = new mongoose.Schema({ age:Number, name: String,x:Number,y:Number});  

If the document is not validated, the document can be saved without the field set by Schema, which can be divided into the following situations

1. Documents that lack fields can be saved successfully

var temp = mongoose.model('temp', schema);
new temp({age:10}).save(function(err,doc){
    //{ __v: 0, age: 10, _id: 597304442b70086a1ce3cf05 }
    console.log(doc);
}); 

2. Documents containing unset fields can also be saved successfully. Unset fields are not saved.

new temp({age:100,abc:"abc"}).save(function(err,doc){
    //{ __v: 0, age: 100, _id: 5973046a2bb57565b474f48b }
    console.log(doc);
}); 

3. Documents containing field types and setting different fields can also be saved successfully. Fields of different field types are saved as field types of settings.

new temp({age:true,name:10}).save(function(err,doc){
    //{ __v: 0, age: 1, name: '10', _id: 597304f7a926033060255366 }
    console.log(doc);
}); 

Through document validation, the following situations can be avoided

Document validation is defined in SchemaType in the following format

{name: {type:String, validator:value}}

Common validations include the following

required: Data must be filled in
default: default value
validate: Custom Matching
min: Minimum (only for numbers)
max: Maximum (only for numbers)
Match: Regular match (only for strings)
enum: Enumeration matching (only for strings)

[required]

Set age to a mandatory field. If there is no age field, the document will not be saved and an error message will appear.

var schema = new mongoose.Schema({ age:{type:Number,required:true}, name: String,x:Number,y:Number});  
var temp = mongoose.model('temp', schema);
new temp({name:"abc"}).save(function(err,doc){
    //Path `age` is required.
    console.log(err.errors['age'].message);
}); 

[default]

Set the default value of the age field to 18. If the age field is not set, the default value will be taken.

var schema = new mongoose.Schema({ age:{type:Number,default:18}, name:String,x:Number,y:Number});  
var temp = mongoose.model('temp', schema);
new temp({name:'a'}).save(function(err,doc){
    //{ __v: 0, name: 'a', _id: 59730d2e7a751d81582210c1, age: 18 }
    console.log(doc);
}); 

[min | max]

Set the value range of age to [0,10]. If age is 20, the document will not be saved and an error message will appear.

var schema = new mongoose.Schema({ age:{type:Number,min:0,max:10}, name: String,x:Number,y:Number});  
var temp = mongoose.model('temp', schema);
new temp({age:20}).save(function(err,doc){
    //Path `age` (20) is more than maximum allowed value (10).
    console.log(err.errors['age'].message);
}); 

[match]

Set the match of name to the'a'character that must exist. If the name does not exist'a', the document will not be saved and an error message will appear.

var schema = new mongoose.Schema({ age:Number, name:{type:String,match:/a/},x:Number,y:Number});  
var temp = mongoose.model('temp', schema);
new temp({name:'bbb'}).save(function(err,doc){
    //Path `name` is invalid (bbb).
    console.log(err.errors['name'].message);
}); 

[enum]

Set the enumeration value of name to ['a','b','c']. If name is not taken within the enumeration range, the document will not be saved and an error prompt will appear.

var schema = new mongoose.Schema({ age:Number, name:{type:String,enum:['a','b','c']},x:Number,y:Number});  
var temp = mongoose.model('temp', schema);
new temp({name:'bbb'}).save(function(err,doc){
    //`bbb` is not a valid enum value for path `name`.
    console.log(err.errors['name'].message);

}); 

[validate]

Validate is actually a function whose parameters represent the current field, return true for validation, return false for non-validation. You can customize any condition with validate. For example, the length of defining a name must be more than four characters

var validateLength = function(arg){
    if(arg.length > 4){
        return true;
    }
    return false;
};
var schema = new mongoose.Schema({ name:{type:String,validate:validateLength}, age:Number,x:Number,y:Number});  
var temp = mongoose.model('temp', schema);
new temp({name:'abc'}).save(function(err,doc){
    //Validator failed for path `name` with value `abc`
    console.log(err.errors['name'].message);
}); 

 

Last

This is roughly what the introduction to mongoose operations is all about. Many operations of mongoose are very similar to those of mongodb, and it is not difficult to learn. However, due to the imperfection of Chinese resources, there is a need for comparison. English Documents It may be a little hard to learn. Moreover, mongoose extends mongodb a lot, adds a lot of methods, and needs more patience.

Welcome to exchange

Posted by batfastad on Tue, 11 Jun 2019 15:19:01 -0700