Mongoose基础入门
<h2>前面的话</h2><p> Mongoose是在node.js异步环境下对mongodb进行便捷操作的对象模型工具。本文将详细介绍如何使用Mongoose来操作MongoDB</p>
<p> </p>
<h3>NodeJS驱动</h3>
<p> 在介绍Mongoose之前,首先介绍使用NodeJS操作MongoDB的方法</p>
<p> 如果使用程序操作数据库,就要使用MongoDB驱动。MongoDB驱动实际上就是为应用程序提供的一个接口,不同的语言对应不同的驱动,NodeJS驱动不能应用在其他后端语言中</p>
<p> 首先,安装mongodb</p>
<div class="cnblogs_code">
<pre>npm install mongodb</pre>
</div>
<p> 接着,使用require()方法引入mongodb数据库;然后使用MongoClient对象的connect()方法连接mongodb;最后通过node来对mongodb进行异步的增删改查</p>
<p> 在mongodb数据库中建立db1数据库,然后通过以下代码,建立col集合,并插入{"a":1}文档</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongodb = require('mongodb'<span style="color: #000000;">);
mongodb.MongoClient.connect(</span>"mongodb://localhost/db1",<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,db){
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
db.collection(</span>"col").insert({"a":1},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,result){
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
console.log(result);
}
})
}
})</span></pre>
</div>
<p> 最后返回结果如下</p>
<div class="cnblogs_code">
<pre>{ result: { ok: 1, n: 1<span style="color: #000000;"> },
ops: [ { a: </span>1<span style="color: #000000;">, _id: 597077dc271d092728caa362 } ],
insertedCount: </span>1<span style="color: #000000;">,
insertedIds: [ 597077dc271d092728caa362 ] }</span></pre>
</div>
<p> </p>
<h3>概述</h3>
<p> Mongoose是NodeJS的驱动,不能作为其他语言的驱动。Mongoose有两个特点</p>
<p> 1、通过关系型数据库的思想来设计非关系型数据库</p>
<p> 2、基于mongodb驱动,简化操作</p>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170721123112068-7289503.jpg" alt="" /></div>
<p> Mongooose中,有三个比较重要的概念,分别是Schema、Model、Entity。它们的关系是:Schema生成Model,Model创造Document,Model和Document都可对数据库操作造成影响,但Model比Document更具操作性</p>
<p><code> Schema</code>用于定义数据库的结构。类似创建表时的数据定义(不仅仅可以定义文档的结构和属性,还可以定义文档的实例方法、静态模型方法、复合索引等),每个<code>Schema</code>会映射到mongodb中的一个collection,<code>Schema</code>不具备操作数据库的能力</p>
<p> Model是由Schema编译而成的构造器,具有抽象属性和行为,可以对数据库进行增删查改。Model的每一个实例(instance)就是一个文档document</p>
<p> Document是由Model创建的实体,它的操作也会影响数据库</p>
<p> </p>
<h3>安装</h3>
<p> 安装nodejs和mongodb之后 ,使用npm来安装mongoose</p>
<div class="cnblogs_code">
<pre>npm install mongoose</pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170720114229505-521707664.png" alt="" /></div>
<p> 安装成功后,就可以通过 require('mongoose') 来使用</p>
<p> </p>
<h3>连接数据库</h3>
<p> 使用require()方法在项目中包含mongoose后,接下来使用connect()方法连接到MongoDB数据库</p>
<p>【connect()】</p>
<div class="cnblogs_code">
<pre>mongoose.connect(url);</pre>
</div>
<p> connect()最简单的使用方式,就是只要传入url参数即可,如下所示。连接到本地localhost的db1服务器</p>
<div class="cnblogs_code">
<pre>mongoose.connect('mongodb://localhost/db1');</pre>
</div>
<p> 如果还需要传递用户名、密码,则可以使用如下方式</p>
<div class="cnblogs_code">
<pre>mongoose.connect('mongodb://username:password@host:port/database?options...');</pre>
</div>
<p> connect()方法还接受一个选项对象options,该对象将传递给底层驱动程序。这里所包含的所有选项优先于连接字符串中传递的选项</p>
<div class="cnblogs_code">
<pre>mongoose.connect(uri, options);</pre>
</div>
<p> 可用选项如下所示</p>
<div class="cnblogs_code">
<pre> db -<span style="color: #000000;">数据库设置
server </span>-<span style="color: #000000;">服务器设置
replset </span>-<span style="color: #000000;">副本集设置
user </span>-<span style="color: #000000;">用户名
pass </span>-<span style="color: #000000;">密码
auth </span>-<span style="color: #000000;">鉴权选项
mongos </span>-连接多个数据库<span style="color: #000000;">
promiseLibrary</span></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> options =<span style="color: #000000;"> {
db: { native_parser: </span><span style="color: #0000ff;">true</span><span style="color: #000000;"> },
server: { poolSize: </span>5<span style="color: #000000;"> },
replset: { rs_name: </span>'myReplicaSetName'<span style="color: #000000;"> },
user: </span>'myUserName'<span style="color: #000000;">,
pass: </span>'myPassword'<span style="color: #000000;">
}
mongoose.connect(uri, options);</span></pre>
</div>
<p> 如果要连接多个数据库,只需要设置多个url以<code>,</code>隔开,同时设置<code>mongos</code>为true</p>
<div class="cnblogs_code">
<pre>mongoose.connect('urlA,urlB,...'<span style="color: #000000;">, {
mongos : </span><span style="color: #0000ff;">true</span><span style="color: #000000;">
})</span></pre>
</div>
<p> connect()函数还接受一个回调参数</p>
<div class="cnblogs_code">
<pre>mongoose.connect(uri, options, <span style="color: #0000ff;">function</span><span style="color: #000000;">(error) {
</span>
});</pre>
</div>
<p> 执行下列代码后,控制台输出“连接成功”</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://localhost/test", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(err){
console.log(</span>'连接失败'<span style="color: #000000;">);
}</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{
console.log(</span>'连接成功'<span style="color: #000000;">);
}
});</span></pre>
</div>
<p> 如果开启鉴权控制,以用户名"u1",密码"123456"登录'db1'数据库。执行代码后,控制台输出“连接成功”</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(err){
console.log(</span>'连接失败'<span style="color: #000000;">);
}</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{
console.log(</span>'连接成功'<span style="color: #000000;">);
}
});</span></pre>
</div>
<p>【disconnect()】 </p>
<div class="cnblogs_code">
<pre>mongoose.disconnect()</pre>
</div>
<p> 使用disconnect()方法可以断开连接</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(err){
console.log(</span>'连接失败'<span style="color: #000000;">);
}</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{
console.log(</span>'连接成功'<span style="color: #000000;">);
}
});
setTimeout(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(){
mongoose.disconnect(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(){
console.log(</span>"断开连接"<span style="color: #000000;">);
})
}, </span>2000);</pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170720232404255-1533749216.gif" alt="" /></div>
<p> </p>
<h3>Schema</h3>
<p> Schema主要用于定义MongoDB中集合Collection里文档document的结构 </p>
<p> 定义Schema非常简单,指定字段名和类型即可,支持的类型包括以下8种</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;">String 字符串
Number 数字
Date 日期
Buffer 二进制
Boolean 布尔值
Mixed 混合类型
ObjectId 对象ID
Array 数组</span></pre>
</div>
<p> 通过mongoose.Schema来调用Schema,然后使用new方法来创建schema对象</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
</span><span style="color: #0000ff;">var</span> Schema =<span style="color: #000000;"> mongoose.Schema;
</span><span style="color: #0000ff;">var</span> mySchema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Schema({
title:String,
author: String,
body: String,
comments: [{ body: String, date: Date }],
date: { type: Date, </span><span style="color: #0000ff;">default</span><span style="color: #000000;">: Date.now },
hidden: Boolean,
meta: {
votes: Number,
favs:Number
}
});</span></pre>
</div>
<p> [注意]创建Schema对象时,声明字段类型有两种方法,一种是首字母大写的字段类型,另一种是引号包含的小写字段类型</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mySchema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Schema({title:String, author:String});
</span><span style="color: #008000;">//</span><span style="color: #008000;">或者 </span>
<span style="color: #0000ff;">var</span> mySchema = <span style="color: #0000ff;">new</span> Schema({title:'string', author:'string'});</pre>
</div>
<p> 如果需要在Schema定义后添加其他字段,可以使用add()方法</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> MySchema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Schema;
MySchema.add({ name: </span>'string', color: 'string', price: 'number' });</pre>
</div>
<p>【timestamps】</p>
<p> 在schema中设置timestamps为true,schema映射的文档document会自动添加createdAt和updatedAt这两个字段,代表创建时间和更新时间</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> UserSchema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Schema(
{...},
{ timestamps: </span><span style="color: #0000ff;">true</span><span style="color: #000000;"> }
);</span></pre>
</div>
<p>【_id】</p>
<p> 每一个文档document都会被mongoose添加一个不重复的_id,_id的数据类型不是字符串,而是ObjectID类型。如果在查询语句中要使用_id,则需要使用findById语句,而不能使用find或findOne语句</p>
<p> </p>
<h3>Model</h3>
<p> 模型Model是根据Schema编译出的构造器,或者称为类,通过Model可以实例化出文档对象document</p>
<p> 文档document的创建和检索都需要通过模型Model来处理</p>
<p>【model()】</p>
<div class="cnblogs_code">
<pre>mongoose.model()</pre>
</div>
<p> 使用model()方法,将Schema编译为Model。model()方法的第一个参数是模型名称</p>
<p> [注意]一定要将model()方法的第一个参数和其返回值设置为相同的值,否则会出现不可预知的结果</p>
<p> Mongoose会将集合名称设置为模型名称的小写版。如果名称的最后一个字符是字母,则会变成复数;如果名称的最后一个字符是数字,则不变;如果模型名称为"MyModel",则集合名称为"mymodels";如果模型名称为"Model1",则集合名称为"model1"</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span> mongoose.Schema({ num:Number, name: String, size: String<span style="color: #000000;">});
</span><span style="color: #0000ff;">var</span> MyModel = mongoose.model('MyModel', schema);</pre>
</div>
<p>【实例化文档document】</p>
<p> 通过对原型Model1使用new方法,实例化出文档document对象</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(err){
console.log(</span>'连接失败'<span style="color: #000000;">);
}</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{
console.log(</span>'连接成功'<span style="color: #000000;">);
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span> mongoose.Schema({ num:Number, name: String, size: String<span style="color: #000000;">});
</span><span style="color: #0000ff;">var</span> MyModel = mongoose.model('MyModel'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">var</span> doc1 = <span style="color: #0000ff;">new</span> MyModel({ size: 'small'<span style="color: #000000;"> });
console.log(doc1.size);</span><span style="color: #008000;">//</span><span style="color: #008000;">'small'</span>
<span style="color: #000000;"> }
});</span></pre>
</div>
<p>【文档保存】</p>
<p> 通过new Model1()创建的文档doc1,必须通过save()方法,才能将创建的文档保存到数据库的集合中,集合名称为模型名称的小写复数版</p>
<p> 回调函数是可选项,第一个参数为err,第二个参数为保存的文档对象</p>
<div class="cnblogs_code">
<pre>save(<span style="color: #0000ff;">function</span> (err, doc) {})</pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ num:Number, name: String, size: String });
</span><span style="color: #0000ff;">var</span> MyModel = mongoose.model('MyModel'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">var</span> doc1 = <span style="color: #0000ff;">new</span> MyModel({ size: 'small'<span style="color: #000000;"> });
doc1.save(</span><span style="color: #0000ff;">function</span><span style="color: #000000;"> (err,doc) {
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ __v: 0, size: 'small', _id: 5970daba61162662b45a24a1 }</span>
<span style="color: #000000;"> console.log(doc);
})
}
});</span></pre>
</div>
<p> 由下图所示,db1数据库中的集合名称为mymodels,里面有一个{size:"small"}的文档</p>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170721003232802-1510769411.png" alt="" /></div>
<p> </p>
<h3>自定义方法</h3>
<p>【实例方法】</p>
<p> <code>Model</code>的实例是<code>document,</code>内置实例方法有很多,如 <code>save</code>,可以通过Schema对象的<code>methods</code>属性给实例自定义扩展方法</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ num:Number, name: String, size: String });
schema.methods.findSimilarSizes </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(cb){
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span>.model('MyModel').find({size:<span style="color: #0000ff;">this</span><span style="color: #000000;">.size},cb);
}
</span><span style="color: #0000ff;">var</span> MyModel = mongoose.model('MyModel'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">var</span> doc1 = <span style="color: #0000ff;">new</span> MyModel({ name:'doc1', size: 'small'<span style="color: #000000;"> });
</span><span style="color: #0000ff;">var</span> doc2 = <span style="color: #0000ff;">new</span> MyModel({ name:'doc2', size: 'small'<span style="color: #000000;"> });
</span><span style="color: #0000ff;">var</span> doc3 = <span style="color: #0000ff;">new</span> MyModel({ name:'doc3', size: 'big'<span style="color: #000000;"> });
doc1.save();
doc2.save();
doc3.save();
setTimeout(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(){
doc1.findSimilarSizes(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
docs.forEach(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(item,index,arr){
</span><span style="color: #008000;">//</span><span style="color: #008000;">doc1</span>
<span style="color: #008000;">//</span><span style="color: #008000;">doc2</span>
<span style="color: #000000;"> console.log(item.name)
})
})
},</span>0<span style="color: #000000;">)
}
});</span></pre>
</div>
<p>【静态方法】</p>
<p> 通过Schema对象的<code>statics</code>属性给 <code>Model</code> 添加静态方法</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ num:Number, name: String, size: String });
schema.statics.findByName </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(name,cb){
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span>.find({name: <span style="color: #0000ff;">new</span> RegExp(name,'i'<span style="color: #000000;">)},cb);
}
</span><span style="color: #0000ff;">var</span> MyModel = mongoose.model('MyModel'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">var</span> doc1 = <span style="color: #0000ff;">new</span> MyModel({ name:'doc1', size: 'small'<span style="color: #000000;"> });
</span><span style="color: #0000ff;">var</span> doc2 = <span style="color: #0000ff;">new</span> MyModel({ name:'doc2', size: 'small'<span style="color: #000000;"> });
</span><span style="color: #0000ff;">var</span> doc3 = <span style="color: #0000ff;">new</span> MyModel({ name:'doc3', size: 'big'<span style="color: #000000;"> });
doc1.save();
doc2.save();
doc3.save();
setTimeout(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(){
MyModel.findByName(</span>'doc1',<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5971e68f4f4216605880dca2,name: 'doc1',size: 'small',__v: 0 } ]</span>
<span style="color: #000000;"> console.log(docs);
})
},</span>0<span style="color: #000000;">)
}
});</span></pre>
</div>
<p> 由上所示,实例方法和静态方法的区别在于,静态方法是通过Schema对象的<code>statics属性</code>给<code>model</code>添加方法,实例方法是通过Schema对象的<code>methods</code>是给document添加方法</p>
<p>【查询方法】</p>
<p> 通过schema对象的query属性,给model添加查询方法</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String});
schema.query.byName </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(name){
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span>.find({name: <span style="color: #0000ff;">new</span><span style="color: #000000;"> RegExp(name)});
}
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
temp.find().byName(</span>'huo').exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;"> { _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 } ]</span>
<span style="color: #000000;"> console.log(docs);
})
}
});</span></pre>
</div>
<p> </p>
<h3>文档新增</h3>
<p> 文档新增有三种方法,一种是使用上面介绍过的文档的save()方法,另一种是使用模型model的create()方法,最后一种是模型model的insertMany()方法</p>
<p>【save()】</p>
<p> [注意]回调函数可以省略</p>
<div class="cnblogs_code">
<pre>save(, , , )</pre>
</div>
<p> 新建{age:10,name:'save'}文档,并保存</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
</span><span style="color: #008000;">//</span><span style="color: #008000;">使用链式写法 </span>
<span style="color: #0000ff;">new</span> temp({age:10,name:'save'}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 59720bc0d2b1125cbcd60b3f, age: 10, name: 'save', __v: 0 } ]</span>
<span style="color: #000000;"> console.log(doc);
});
}
});</span></pre>
</div>
<p>【create()】</p>
<p> 使用save()方法,需要先实例化为文档,再使用save()方法保存文档。而create()方法,则直接在模型Model上操作,并且可以同时新增多个文档</p>
<div class="cnblogs_code">
<pre>Model.create(doc(s), )</pre>
</div>
<p> 新增{name:"xiaowang"},{name:"xiaoli"}这两个文档</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
temp.create({name:</span>"xiaowang"},{name:"xiaoli"},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc1,doc2){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ __v: 0, name: 'xiaowang', _id: 59720d83ad8a953f5cd04664 }</span>
<span style="color: #000000;"> console.log(doc1);
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ __v: 0, name: 'xiaoli', _id: 59720d83ad8a953f5cd04665 }</span>
<span style="color: #000000;"> console.log(doc2);
});
}
});</span></pre>
</div>
<p>【insertMany()】</p>
<div class="cnblogs_code">
<pre>Model.insertMany(doc(s), , )</pre>
</div>
<p> 新增{name:"a"},{name:"b"}这两个文档</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
temp.insertMany([{name:</span>"a"},{name:"b"}],<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { __v: 0, name: 'a', _id: 59720ea1bbf5792af824b30c },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ __v: 0, name: 'b', _id: 59720ea1bbf5792af824b30d } ]</span>
<span style="color: #000000;"> console.log(docs);
});
}
});</span></pre>
</div>
<p> </p>
<h3>文档查询</h3>
<p> 使用Mongoose来查找文档很容易,有以下3种方法可供选择</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;">find()
findById()
findOne()<br /></span></pre>
</div>
<p>【find()】</p>
<p> 第一个参数表示查询条件,第二个参数用于控制返回的字段,第三个参数用于配置查询参数,第四个参数是回调函数,回调函数的形式为function(err,docs){}</p>
<div class="cnblogs_code">
<pre>Model.find(conditions, , , )</pre>
</div>
<p> 在数据库db1的集合temps中存在如下数据</p>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170721205332902-619241772.png" alt="" /></div>
<p> 现在,使用find()方法找出所有数据</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
temp.find(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86d, name: 'wang', age: 18 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86f, name: 'li', age: 12 } ]</span>
<span style="color: #000000;"> console.log(docs);
})
}
});</span></pre>
</div>
<p> 找出年龄大于18的数据</p>
<div class="cnblogs_code">
<pre> temp.find({age:{$gte:18}},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86d, name: 'wang', age: 18 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 }]</span>
<span style="color: #000000;"> console.log(docs);
})</span></pre>
</div>
<p> 找出年龄大于18且名字里存在'huo'的数据</p>
<div class="cnblogs_code">
<pre> temp.find({name:/huo/,age:{$gte:18}},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 }]</span>
<span style="color: #000000;"> console.log(docs);
})</span></pre>
</div>
<p> 找出名字里存在'a'的数据,且只输出'name'字段</p>
<p> [注意]_id字段默认输出</p>
<div class="cnblogs_code">
<pre> temp.find({name:/a/},'name',<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5971f93be6f98ec60e3dc86c, name: 'huochai' },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86d, name: 'wang' } ]</span>
<span style="color: #000000;"> console.log(docs);
})</span></pre>
</div>
<p> 如果确实不需要_id字段输出,可以进行如下设置</p>
<div class="cnblogs_code">
<pre> temp.find({name:/a/},{name:1,_id:0},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { name: 'huochai' }, { name: 'wang' } ]</span>
<span style="color: #000000;"> console.log(docs);
})</span></pre>
</div>
<p> 找出跳过前两条数据的其他所有数据</p>
<p> [注意]如果使用第三个参数,前两个参数如果没有值,需要设置为null</p>
<div class="cnblogs_code">
<pre> temp.find(<span style="color: #0000ff;">null</span>,<span style="color: #0000ff;">null</span>,{skip:2},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 30 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86f, name: 'li', age: 12 } ]</span>
<span style="color: #000000;"> console.log(docs);
})</span></pre>
</div>
<p>【findById()】</p>
<div class="cnblogs_code">
<pre>Model.findById(id, , , )</pre>
</div>
<p> 显示第0个元素的所有字段</p>
<div class="cnblogs_code">
<pre> <span style="color: #0000ff;">var</span> aIDArr =<span style="color: #000000;"> [];
temp.find(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
docs.forEach(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(item,index,arr){
aIDArr.push(item._id);
})
temp.findById(aIDArr[</span>0],<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }</span>
<span style="color: #000000;"> console.log(doc);
})
})</span></pre>
</div>
<p> 以上代码的另一种写法如下</p>
<div class="cnblogs_code">
<pre> <span style="color: #0000ff;">var</span> aIDArr =<span style="color: #000000;"> [];
temp.find(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
docs.forEach(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(item,index,arr){
aIDArr.push(item._id);
})
temp.findById(aIDArr[</span>0]).exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }</span>
<span style="color: #000000;"> console.log(doc);
})
})</span></pre>
</div>
<p> 只输出name字段</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;"> temp.findById(aIDArr[</span>0],{name:1,_id:0},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{name: 'huochai'}</span>
<span style="color: #000000;"> console.log(doc);
}) <br /></span></pre>
</div>
<p> 或者写成下面这种形式</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;"> temp.findById(aIDArr[</span>0],{name:1,_id:0}).exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{name: 'huochai'}</span>
<span style="color: #000000;"> console.log(doc);
}) <br /></span></pre>
</div>
<p> 输出最少的字段</p>
<div class="cnblogs_code">
<pre> temp.findById(aIDArr,{lean:<span style="color: #0000ff;">true</span>},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c }</span>
<span style="color: #000000;"> console.log(doc);
})
temp.findById(aIDArr[</span>0],{lean:<span style="color: #0000ff;">true</span>}).exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c }</span>
<span style="color: #000000;"> console.log(doc);
}) </span></pre>
</div>
<p>【findOne()】</p>
<p> 该方法返回查找到的所有实例的第一个</p>
<div class="cnblogs_code">
<pre>Model.findOne(, , , )</pre>
</div>
<p> 找出age>20的文档中的第一个文档</p>
<div class="cnblogs_code">
<pre>temp.findOne({age:{$gt : 20}},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }</span>
<span style="color: #000000;"> console.log(doc);
})
temp.findOne({age:{$gt : </span>20}}).exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 27 }</span>
<span style="color: #000000;"> console.log(doc);
})</span></pre>
</div>
<p> 找出age>20的文档中的第一个文档,且只输出name字段</p>
<div class="cnblogs_code">
<pre>temp.findOne({age:{$gt : 20}},{name:1,_id:0},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ name: 'huochai' }</span>
<span style="color: #000000;"> console.log(doc);
})
temp.findOne({age:{$gt : </span>20}},{name:1,_id:0}).exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ name: 'huochai' }</span>
<span style="color: #000000;"> console.log(doc);
}) </span></pre>
</div>
<p> 找出age>20的文档中的第一个文档,且输出包含name字段在内的最短字段</p>
<div class="cnblogs_code">
<pre>temp.findOne({age:{$gt : 20}},"name",{lean:<span style="color: #0000ff;">true</span>},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai' }</span>
<span style="color: #000000;"> console.log(doc);
})
temp.findOne({age:{$gt : </span>20}},"name").lean().exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai' }</span>
<span style="color: #000000;"> console.log(doc);
}) </span></pre>
</div>
<p> 文档查询中,常用的查询条件如下</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;">$or 或关系
$nor 或关系取反
$gt 大于
$gte 大于等于
$lt 小于
$lte 小于等于
$ne 不等于
$</span><span style="color: #0000ff;">in</span><span style="color: #000000;"> 在多个值范围内
$nin 不在多个值范围内
$all 匹配数组中多个值
$regex 正则,用于模糊查询
$size 匹配数组大小
$maxDistance 范围查询,距离(基于LBS)
$mod 取模运算
$near 邻域查询,查询附近的位置(基于LBS)
$exists 字段是否存在
$elemMatch 匹配内数组内的元素
$within 范围查询(基于LBS)
$box 范围查询,矩形范围(基于LBS)
$center 范围醒询,圆形范围(基于LBS)
$centerSphere 范围查询,球形范围(基于LBS)
$slice 查询字段集合中的元素(比如从第几个之后,第N到第M个元素</span></pre>
</div>
<p>【$where】</p>
<p> 如果要进行更复杂的查询,需要使用<span style="color: #888888;">$where</span>操作符,$where操作符功能强大而且灵活,它可以使用任意的JavaScript作为查询的一部分,包含JavaScript表达式的字符串或者JavaScript函数</p>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722141433964-2137472445.png" alt="" /></div>
<p> 使用字符串</p>
<div class="cnblogs_code">
<pre>temp.find({$where:"this.x == this.y"},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]</span>
<span style="color: #000000;"> console.log(docs);
}) </span></pre>
</div>
<div class="cnblogs_code">
<pre>temp.find({$where:"obj.x == obj.y"},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]</span>
<span style="color: #000000;"> console.log(docs);
}) </span></pre>
</div>
<p> 使用函数</p>
<div class="cnblogs_code">
<pre>temp.find({$where:<span style="color: #0000ff;">function</span><span style="color: #000000;">(){
</span><span style="color: #0000ff;">return</span> obj.x !==<span style="color: #000000;"> obj.y;
}},</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 } ]</span>
<span style="color: #000000;"> console.log(docs);
}) </span></pre>
</div>
<div class="cnblogs_code">
<pre>temp.find({$where:<span style="color: #0000ff;">function</span><span style="color: #000000;">(){
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span>.x !== <span style="color: #0000ff;">this</span><span style="color: #000000;">.y;
}},</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 } ]</span>
<span style="color: #000000;"> console.log(docs);
}) </span></pre>
</div>
<p> </p>
<h3>文档更新</h3>
<p> 文档更新可以使用以下几种方法</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;">update()
updateMany()<br />find() + save()
updateOne()<br />findOne() + save()
findByIdAndUpdate()
fingOneAndUpdate()</span></pre>
</div>
<p> 【update()】</p>
<p> 第一个参数conditions为查询条件,第二个参数doc为需要修改的数据,第三个参数options为控制选项,第四个参数是回调函数</p>
<div class="cnblogs_code">
<pre>Model.update(conditions, doc, , )</pre>
</div>
<p> options有如下选项</p>
<div class="cnblogs_code">
<pre> safe (<span style="color: #0000ff;">boolean</span><span style="color: #000000;">): 默认为true。安全模式。
upsert (</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">): 默认为false。如果不存在则创建新记录。
multi (</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">): 默认为false。是否更新多个查询记录。
runValidators: 如果值为true,执行Validation验证。
setDefaultsOnInsert: 如果upsert选项为true,在新建时插入文档定义的默认值。
strict (</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">): 以strict模式进行更新。
overwrite (</span><span style="color: #0000ff;">boolean</span>): 默认为false。禁用update-only模式,允许覆盖记录。</pre>
</div>
<p> 数据库temps中现有数据如下</p>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722102511714-669069142.png" alt="" /></div>
<p> 现在使用update()方法查询age大于20的数据,并将其年龄更改为40岁</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
temp.update({age:{$gte:</span>20}},{age:40},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,raw){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ n: 1, nModified: 1, ok: 1 }</span>
<span style="color: #000000;"> console.log(raw);
})
}
});</span></pre>
</div>
<p> 经过以上操作,数据库结果如下。只有第一个数据更改为40岁。而第三个数据没有发生变化</p>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722103806792-1390059167.png" alt="" /></div>
<p> 如果要同时更新多个记录,需要设置options里的multi为true。下面将名字中有'a'字符的年龄设置为10岁</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> mongoose = require('mongoose'<span style="color: #000000;">);
mongoose.connect(</span>"mongodb://u1:123456@localhost/db1", <span style="color: #0000ff;">function</span><span style="color: #000000;">(err) {
</span><span style="color: #0000ff;">if</span>(!<span style="color: #000000;">err){
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
temp.update({name:</span>/a/},{age: 10},{multi:<span style="color: #0000ff;">true</span>},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,raw){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ n: 2, nModified: 2, ok: 1 }</span>
<span style="color: #000000;"> console.log(raw);
})
}
});</span></pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722105348933-1661967582.png" alt="" /></div>
<p> 如果设置的查找条件,数据库里的数据并不满足,默认什么事都不发生</p>
<div class="cnblogs_code">
<pre>temp.update({age:100},{name: "hundred"},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,raw){
//{ n: </span>0, nModified: 0, ok: 1<span style="color: #000000;"> }
console.log(raw);
})</span></pre>
</div>
<p> 如果设置options里的upsert参数为true,若没有符合查询条件的文档,mongo将会综合第一第二个参数向集合插入一个新的文档</p>
<div class="cnblogs_code">
<pre>temp.update({age:100},{name: "hundred"},{upsert:<span style="color: #0000ff;">true</span>},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,raw){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ n: 1, nModified: 0,upserted: [ { index: 0, _id: 5972c202d46b621fca7fc8c7 } ], ok: 1 }</span>
<span style="color: #000000;"> console.log(raw);
})</span></pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722111059777-351477732.png" alt="" /></div>
<div class="cnblogs_code">
<pre>temp.update({name:/aa/},{age: 0},{upsert:<span style="color: #0000ff;">true</span>},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,raw){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ n: 1, nModified: 0,upserted: [ { index: 0, _id: 5972c288d46b621fca7fdd8f } ], ok: 1 }</span>
<span style="color: #000000;"> console.log(raw);
})</span></pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722111300761-1926802847.png" alt="" /></div>
<p> [注意]update()方法中的回调函数不能省略,否则数据不会被更新。如果回调函数里并没有什么有用的信息,则可以使用exec()简化代码</p>
<div class="cnblogs_code">
<pre>temp.update({name:/aa/},{age: 0},{upsert:<span style="color: #0000ff;">true</span>}).exec();</pre>
</div>
<p>【updateMany()】</p>
<p> updateMany()与update()方法唯一的区别就是默认更新多个文档,即使设置{multi:false}也无法只更新第一个文档</p>
<div class="cnblogs_code">
<pre>Model.updateMany(conditions, doc, , )</pre>
</div>
<p> 将数据库中名字中带有'huo'的数据,年龄变为50岁</p>
<div class="cnblogs_code">
<pre>temp.updateMany({name:/huo/},{age:50},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,raw){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ n: 2, nModified: 2, ok: 1 }</span>
<span style="color: #000000;"> console.log(raw);
});<br /></span></pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722112834308-1873815423.png" alt="" /></div>
<p>【find() + save()】</p>
<p> 如果需要更新的操作比较复杂,可以使用find()+save()方法来处理,比如找到年龄小于30岁的数据,名字后面添加'30'字符</p>
<div class="cnblogs_code">
<pre>temp.find({age:{$lt:20}},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5971f93be6f98ec60e3dc86d, name: 'wang', age: 10 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86f, name: 'li', age: 12 }]</span>
<span style="color: #000000;"> console.log(docs);
docs.forEach(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(item,index,arr){
item.name </span>+= '30'<span style="color: #000000;">;
item.save();
})
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5971f93be6f98ec60e3dc86d, name: 'wang30', age: 10 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;"> { _id: 5971f93be6f98ec60e3dc86f, name: 'li30', age: 12 }]</span>
<span style="color: #000000;"> console.log(docs);
});</span></pre>
</div>
<p>【updateOne()】</p>
<p> updateOne()方法只能更新找到的第一条数据,即使设置{multi:true}也无法同时更新多个文档</p>
<p> 将数据库中名字中带有'huo'的数据,年龄变为60岁</p>
<div class="cnblogs_code">
<pre>temp.updateOne({name:/huo/},{age:60},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,raw){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ n: 1, nModified: 1, ok: 1 }</span>
<span style="color: #000000;"> console.log(raw);
});</span></pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722113216183-374293061.png" alt="" /></div>
<p>【findOne() + save()】</p>
<p> 如果需要更新的操作比较复杂,可以使用findOne()+save()方法来处理,比如找到名字为'huochai'的数据,年龄加100岁</p>
<div class="cnblogs_code">
<pre>temp.findOne({name:'huochai'},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 10 }</span>
<span style="color: #000000;"> console.log(doc);
doc.age </span>+= 100<span style="color: #000000;">;
doc.save();
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 110 }</span>
<span style="color: #000000;"> console.log(doc);
});</span></pre>
</div>
<p>【findOneAndUpdate()】</p>
<p> fineOneAndUpdate()方法的第四个参数回调函数的形式如下function(err,doc){}</p>
<div class="cnblogs_code">
<pre>Model.findOneAndUpdate(, , , )</pre>
</div>
<p>【findByIdAndUpdate】</p>
<p> fineByIdAndUpdate()方法的第四个参数回调函数的形式如下function(err,doc){}</p>
<div class="cnblogs_code">
<pre>Model.findOneAndUpdate(, , , )</pre>
</div>
<p> </p>
<h3>文档删除</h3>
<p> 有三种方法用于文档删除</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;">remove()
findOneAndRemove()
findByIdAndRemove()</span></pre>
</div>
<p>【remove()】</p>
<p> remove有两种形式,一种是文档的remove()方法,一种是Model的remove()方法</p>
<p> 下面介绍Model的remove()方法,该方法的第一个参数conditions为查询条件,第二个参数回调函数的形式如下function(err){} </p>
<div class="cnblogs_code">
<pre>model.remove(conditions, )</pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722115955136-435160244.png" alt="" /></div>
<p> 删除数据库中名称包括'30'的数据</p>
<div class="cnblogs_code">
<pre>temp.remove({name:/30/},<span style="color: #0000ff;">function</span>(err){})</pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722120740730-207409461.png" alt="" /></div>
<p> [注意]remove()方法中的回调函数不能省略,否则数据不会被删除。当然,可以使用exec()方法来简写代码</p>
<div class="cnblogs_code">
<pre>temp.remove({name:/30/}).exec()</pre>
</div>
<p> 下面介绍文档的remove()方法,该方法的参数回调函数的形式如下function(err,doc){}</p>
<div class="cnblogs_code">
<pre>document.remove()</pre>
</div>
<p> 删除数据库中名称包含'huo'的数据</p>
<p> [注意]文档的remove()方法的回调函数参数可以省略</p>
<div class="cnblogs_code">
<pre>temp.find({name:/huo/},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
doc.forEach(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(item,index,arr){
item.remove(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86c, name: 'huochai', age: 30 }</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5971f93be6f98ec60e3dc86e, name: 'huo', age: 60 }</span>
<span style="color: #000000;"> console.log(doc);
})
})
})</span></pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722121538620-1318315817.png" alt="" /></div>
<p>【findOneAndRemove()】</p>
<p> model的remove()会删除符合条件的所有数据,如果只删除符合条件的第一条数据,则可以使用model的findOneAndRemove()方法</p>
<div class="cnblogs_code">
<pre>Model.findOneAndRemove(conditions, , )</pre>
</div>
<p> 集合temps现有数据如下</p>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722122724527-1611550236.png" alt="" /></div>
<p> 现在删除第一个年龄小于20的数据</p>
<div class="cnblogs_code">
<pre>temp.findOneAndRemove({age:{$lt:20}},<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972d3f3e6f98ec60e3dc873, name: 'wang', age: 18 }</span>
<span style="color: #000000;"> console.log(doc);
})</span></pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722123723214-1991458770.png" alt="" /></div>
<p> 与model的remove()方法相同,回调函数不能省略,否则数据不会被删除。当然,可以使用exec()方法来简写代码</p>
<div class="cnblogs_code">
<pre>temp.findOneAndRemove({age:{$lt:20}}).exec()</pre>
</div>
<p>【findByIdAndRemove()】</p>
<div class="cnblogs_code">
<pre>Model.findByIdAndRemove(id, , )</pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722124111839-168768226.png" alt="" /></div>
<p> 删除第0个元素</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> aIDArr =<span style="color: #000000;"> [];
temp.find(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
docs.forEach(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(item,index,arr){
aIDArr.push(item._id);
})
temp.findByIdAndRemove(aIDArr[</span>0],<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972d754e6f98ec60e3dc882, name: 'huochai', age: 27 }</span>
<span style="color: #000000;"> console.log(doc);
})
})</span></pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722124210105-1759533603.png" alt="" /></div>
<p> 类似的,该方法也不能省略回调函数,否则数据不会被删除。当然,可以使用exec()方法来简写代码</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> aIDArr =<span style="color: #000000;"> [];
temp.find(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
docs.forEach(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(item,index,arr){
aIDArr.push(item._id);
})
temp.findByIdAndRemove(aIDArr[</span>0<span style="color: #000000;">]).exec()
})</span></pre>
</div>
<div><img src="https://images2015.cnblogs.com/blog/740839/201707/740839-20170722124335949-2088054111.png" alt="" /></div>
<p> </p>
<h3>前后钩子</h3>
<p> 前后钩子即pre()和post()方法,又称为中间件,是在执行某些操作时可以执行的函数。中间件在schema上指定,类似于静态方法或实例方法等</p>
<p> 可以在数据库执行下列操作时,设置前后钩子</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;"> init
validate
save
remove
count
find
findOne
findOneAndRemove
findOneAndUpdate
insertMany
update</span></pre>
</div>
<p>【pre()】</p>
<p> 以find()方法为例,在执行find()方法之前,执行pre()方法</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String,x:Number,y:Number});
schema.pre(</span>'find',<span style="color: #0000ff;">function</span><span style="color: #000000;">(next){
console.log(</span>'我是pre方法1'<span style="color: #000000;">);
next();
});
schema.pre(</span>'find',<span style="color: #0000ff;">function</span><span style="color: #000000;">(next){
console.log(</span>'我是pre方法2'<span style="color: #000000;">);
next();
});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
temp.find(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
console.log(docs[</span>0<span style="color: #000000;">]);
})
</span><span style="color: #008000;">/*</span><span style="color: #008000;">
我是pre方法1
我是pre方法2
{ _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 }
</span><span style="color: #008000;">*/</span></pre>
</div>
<p>【post()】</p>
<p> post()方法并不是在执行某些操作后再去执行的方法,而在执行某些操作前最后执行的方法,post()方法里不可以使用next()</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String,x:Number,y:Number});
schema.post(</span>'find',<span style="color: #0000ff;">function</span><span style="color: #000000;">(docs){
console.log(</span>'我是post方法1'<span style="color: #000000;">);
});
schema.post(</span>'find',<span style="color: #0000ff;">function</span><span style="color: #000000;">(docs){
console.log(</span>'我是post方法2'<span style="color: #000000;">);
});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
temp.find(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
console.log(docs[</span>0<span style="color: #000000;">]);
})
</span><span style="color: #008000;">/*</span><span style="color: #008000;">
我是post方法1
我是post方法2
{ _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 }
</span><span style="color: #008000;">*/</span> </pre>
</div>
<p> </p>
<h3>查询后处理</h3>
<p> 常用的查询后处理的方法如下所示</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;">sort 排序<br />skip 跳过
limit 限制
select 显示字段
exect 执行<br />count 计数<br />distinct 去重</span></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ age:Number, name: String,x:Number,y:Number});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
temp.find(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]</span>
<span style="color: #000000;"> console.log(docs);
}) </span></pre>
</div>
<p>【sort()】</p>
<p> 按age从小到大排序</p>
<div class="cnblogs_code">
<pre>temp.find().sort("age").exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 } ]</span>
<span style="color: #000000;"> console.log(docs);
}); </span></pre>
</div>
<p> 按x从小到大,age从大到小排列</p>
<div class="cnblogs_code">
<pre>temp.find().sort("x -age").exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{_id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]</span>
<span style="color: #000000;"> console.log(docs);
}); </span></pre>
</div>
<p>【skip()】</p>
<p> 跳过1个,显示其他</p>
<div class="cnblogs_code">
<pre>temp.find().skip(1).exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc888, name: 'huo', age: 30, x: 2, y: 1 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc889, name: 'li', age: 20, x: 2, y: 2 } ]</span>
<span style="color: #000000;"> console.log(docs);
}); </span></pre>
</div>
<p>【limit()】</p>
<p> 显示2个</p>
<div class="cnblogs_code">
<pre>temp.find().limit(2).exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { _id: 5972ed35e6f98ec60e3dc886,name: 'huochai',age: 27,x: 1,y: 2 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ _id: 5972ed35e6f98ec60e3dc887,name: 'wang',age: 18,x: 1,y: 1 } ]</span>
<span style="color: #000000;"> console.log(docs);
}); </span></pre>
</div>
<p>【select()】</p>
<p> 显示name、age字段,不显示_id字段</p>
<div class="cnblogs_code">
<pre>temp.find().select("name age -_id").exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { name: 'huochai', age: 27 },{ name: 'wang', age: 18 },{ name: 'huo', age: 30 },{ name: 'li', age: 20 } ]</span>
<span style="color: #000000;"> console.log(docs);
}); </span></pre>
</div>
<div class="cnblogs_code">
<pre>temp.find().select({name:1, age:1, _id:0}).exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { name: 'huochai', age: 27 },{ name: 'wang', age: 18 },{ name: 'huo', age: 30 },{ name: 'li', age: 20 } ]</span>
<span style="color: #000000;"> console.log(docs);
}); </span></pre>
</div>
<p> 下面将以上方法结合起来使用,跳过第1个后,只显示2个数据,按照age由大到小排序,且不显示_id字段</p>
<div class="cnblogs_code">
<pre>temp.find().skip(1).limit(2).sort("-age").select("-_id").exec(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,docs){
</span><span style="color: #008000;">//</span><span style="color: #008000;">[ { name: 'huochai', age: 27, x: 1, y: 2 },</span>
<span style="color: #008000;">//</span><span style="color: #008000;">{ name: 'li', age: 20, x: 2, y: 2 } ]</span>
<span style="color: #000000;"> console.log(docs);
}); </span></pre>
</div>
<p>【count()】</p>
<p> 显示集合temps中的文档数量</p>
<div class="cnblogs_code">
<pre>temp.find().count(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,count){
console.log(count);</span><span style="color: #008000;">//</span><span style="color: #008000;">4</span>
}); </pre>
</div>
<p>【distinct()】</p>
<p> 返回集合temps中的x的值</p>
<div class="cnblogs_code">
<pre>temp.find().distinct('x',<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,distinct){
console.log(distinct);</span><span style="color: #008000;">//</span><span style="color: #008000;">[ 1, 2 ]</span>
}); </pre>
</div>
<p> </p>
<h3>文档验证</h3>
<p> 为什么需要文档验证呢?以一个例子作为说明,schema进行如下定义</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span> mongoose.Schema({ age:Number, name: String,x:Number,y:Number});</pre>
</div>
<p> 如果不进行文档验证,保存文档时,就可以不按照Schema设置的字段进行设置,分为以下几种情况</p>
<p> 1、缺少字段的文档可以保存成功</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">new</span> temp({age:10}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ __v: 0, age: 10, _id: 597304442b70086a1ce3cf05 }</span>
<span style="color: #000000;"> console.log(doc);
}); </span></pre>
</div>
<p> 2、包含未设置的字段的文档也可以保存成功,未设置的字段不被保存</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">new</span> temp({age:100,abc:"abc"}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ __v: 0, age: 100, _id: 5973046a2bb57565b474f48b }</span>
<span style="color: #000000;"> console.log(doc);
}); </span></pre>
</div>
<p> 3、包含字段类型与设置不同的字段的文档也可以保存成功,不同字段类型的字段被保存为设置的字段类型</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">new</span> temp({age:<span style="color: #0000ff;">true</span>,name:10}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ __v: 0, age: 1, name: '10', _id: 597304f7a926033060255366 }</span>
<span style="color: #000000;"> console.log(doc);
}); </span></pre>
</div>
<p> 而通过文档验证,就可以避免以下几种情况发生</p>
<p class="tgt"> 文档验证在SchemaType中定义,格式如下</p>
<div class="cnblogs_code">
<pre>{name: {type:String, validator:value}}</pre>
</div>
<p> 常用验证包括以下几种</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;">required: 数据必须填写
</span><span style="color: #0000ff;">default</span><span style="color: #000000;">: 默认值
validate: 自定义匹配
min: 最小值(只适用于数字)
max: 最大值(只适用于数字)
match: 正则匹配(只适用于字符串)
enum:枚举匹配(只适用于字符串)</span></pre>
</div>
<p>【required】</p>
<p> 将age设置为必填字段,如果没有age字段,文档将不被保存,且出现错误提示</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span> mongoose.Schema({ age:{type:Number,required:<span style="color: #0000ff;">true</span><span style="color: #000000;">}, name: String,x:Number,y:Number});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">new</span> temp({name:"abc"}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">Path `age` is required.</span>
console.log(err.errors['age'<span style="color: #000000;">].message);
}); </span></pre>
</div>
<p>【default】</p>
<p> 设置age字段的默认值为18,如果不设置age字段,则会取默认值</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span> mongoose.Schema({ age:{type:Number,<span style="color: #0000ff;">default</span>:18<span style="color: #000000;">}, name:String,x:Number,y:Number});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">new</span> temp({name:'a'}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">{ __v: 0, name: 'a', _id: 59730d2e7a751d81582210c1, age: 18 }</span>
<span style="color: #000000;"> console.log(doc);
}); </span></pre>
</div>
<p>【min | max】</p>
<p> 将age的取值范围设置为。如果age取值为20,文档将不被保存,且出现错误提示</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span> mongoose.Schema({ age:{type:Number,min:0,max:10<span style="color: #000000;">}, name: String,x:Number,y:Number});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">new</span> temp({age:20}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">Path `age` (20) is more than maximum allowed value (10).</span>
console.log(err.errors['age'<span style="color: #000000;">].message);
}); </span></pre>
</div>
<p>【match】</p>
<p> 将name的match设置为必须存在'a'字符。如果name不存在'a',文档将不被保存,且出现错误提示</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span> mongoose.Schema({ age:Number, name:{type:String,match:/a/<span style="color: #000000;">},x:Number,y:Number});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">new</span> temp({name:'bbb'}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">Path `name` is invalid (bbb).</span>
console.log(err.errors['name'<span style="color: #000000;">].message);
}); </span></pre>
</div>
<p>【enum】</p>
<p> 将name的枚举取值设置为['a','b','c'],如果name不在枚举范围内取值,文档将不被保存,且出现错误提示</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span> mongoose.Schema({ age:Number, name:{type:String,enum:['a','b','c'<span style="color: #000000;">]},x:Number,y:Number});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">new</span> temp({name:'bbb'}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">`bbb` is not a valid enum value for path `name`.</span>
console.log(err.errors['name'<span style="color: #000000;">].message);
}); </span></pre>
</div>
<p>【validate】</p>
<p> validate实际上是一个函数,函数的参数代表当前字段,返回true表示通过验证,返回false表示未通过验证。利用validate可以自定义任何条件。比如,定义名字name的长度必须在4个字符以上</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">var</span> validateLength = <span style="color: #0000ff;">function</span><span style="color: #000000;">(arg){
</span><span style="color: #0000ff;">if</span>(arg.length > 4<span style="color: #000000;">){
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">;
}
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">;
};
</span><span style="color: #0000ff;">var</span> schema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> mongoose.Schema({ name:{type:String,validate:validateLength}, age:Number,x:Number,y:Number});
</span><span style="color: #0000ff;">var</span> temp = mongoose.model('temp'<span style="color: #000000;">, schema);
</span><span style="color: #0000ff;">new</span> temp({name:'abc'}).save(<span style="color: #0000ff;">function</span><span style="color: #000000;">(err,doc){
</span><span style="color: #008000;">//</span><span style="color: #008000;">Validator failed for path `name` with value `abc`</span>
console.log(err.errors['name'<span style="color: #000000;">].message);
}); </span></pre>
</div>
<p> </p>
<h3>联表操作</h3>
<p> 下面以一个实例的形式来介绍下mongoose中的联表操作population</p>
<p> 以类别category和文章post之间的关联为例</p>
<p> 其中,category的model如下所示</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">const</span> mongoose = require(<span style="color: #800000;">'</span><span style="color: #800000;">mongoose</span><span style="color: #800000;">'</span><span style="color: #000000;">)
</span><span style="color: #0000ff;">const</span> Schema =<span style="color: #000000;"> mongoose.Schema
</span><span style="color: #0000ff;">const</span> CategorySchema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Schema(
{
number: { type: Number, required: </span><span style="color: #0000ff;">true</span>, index: <span style="color: #0000ff;">true</span>, unique: <span style="color: #0000ff;">true</span>, min:[<span style="color: #800080;">1000000000</span>, <span style="color: #800000;">'</span><span style="color: #800000;">位数不足</span><span style="color: #800000;">'</span>], max: [<span style="color: #800080;">9999999999</span>, <span style="color: #800000;">'</span><span style="color: #800000;">位数过长</span><span style="color: #800000;">'</span><span style="color: #000000;">] },
name: { type: String, required: </span><span style="color: #0000ff;">true</span>, validate: { validator: (v) => v.trim().length, message: <span style="color: #800000;">'</span><span style="color: #800000;">名称不能为空</span><span style="color: #800000;">'</span><span style="color: #000000;">} },
description: { type: String },
posts: [{ type: Schema.Types.ObjectId, </span><span style="color: #0000ff;">ref</span>: <span style="color: #800000;">'</span><span style="color: #800000;">Post</span><span style="color: #800000;">'</span><span style="color: #000000;"> }],
recommend: { type: Boolean },
index: { type: Number }
},
{ timestamps: </span><span style="color: #0000ff;">true</span><span style="color: #000000;"> }
)
module.exports </span>= mongoose.model(<span style="color: #800000;">'</span><span style="color: #800000;">Category</span><span style="color: #800000;">'</span>, CategorySchema)</pre>
</div>
<p> post的model如下所示</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">const</span> mongoose = require(<span style="color: #800000;">'</span><span style="color: #800000;">mongoose</span><span style="color: #800000;">'</span><span style="color: #000000;">)
</span><span style="color: #0000ff;">const</span> Schema =<span style="color: #000000;"> mongoose.Schema
</span><span style="color: #0000ff;">const</span> PostSchema = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Schema(
{
title: { type: String, required: </span><span style="color: #0000ff;">true</span>, unique: <span style="color: #0000ff;">true</span><span style="color: #000000;"> },
description: { type: String },
content: { type: String },
category: { type: Schema.Types.ObjectId, </span><span style="color: #0000ff;">ref</span>: <span style="color: #800000;">'</span><span style="color: #800000;">Category</span><span style="color: #800000;">'</span>, index: <span style="color: #0000ff;">true</span><span style="color: #000000;"> },
comments: [{ type: Schema.Types.ObjectId, </span><span style="color: #0000ff;">ref</span>: <span style="color: #800000;">'</span><span style="color: #800000;">Comment</span><span style="color: #800000;">'</span><span style="color: #000000;"> }],
likes: [{ type: Schema.Types.ObjectId, </span><span style="color: #0000ff;">ref</span>: <span style="color: #800000;">'</span><span style="color: #800000;">Like</span><span style="color: #800000;">'</span><span style="color: #000000;"> }],
imgUrl: { type: String },
recommend: { type: Boolean },
index: { type: Number }
},
{
timestamps: </span><span style="color: #0000ff;">true</span><span style="color: #000000;">
}
)
module.exports </span>= mongoose.model(<span style="color: #800000;">'</span><span style="color: #800000;">Post</span><span style="color: #800000;">'</span>, PostSchema)</pre>
</div>
<p> 在对类别的操作中, 都需要使用populate操作符显示出所包括的posts中的title</p>
<div class="cnblogs_code">
<pre><span style="color: #008000;">/*</span><span style="color: #008000;"> 加载所有类别 </span><span style="color: #008000;">*/</span><span style="color: #000000;">
app.</span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">'</span><span style="color: #800000;">/categories</span><span style="color: #800000;">'</span>, (req, res) =><span style="color: #000000;"> {
Category.find().populate(</span><span style="color: #800000;">'</span><span style="color: #800000;">posts</span><span style="color: #800000;">'</span>,<span style="color: #800000;">'</span><span style="color: #800000;">title</span><span style="color: #800000;">'</span>).<span style="color: #0000ff;">select</span>(<span style="color: #800000;">"</span><span style="color: #800000;">number name description recommend index</span><span style="color: #800000;">"</span>).exec((err, docs) =><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({code: <span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err})
</span><span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">200</span>).json({code: <span style="color: #800080;">1</span>, message: <span style="color: #800000;">'</span><span style="color: #800000;">获取类别成功</span><span style="color: #800000;">'</span><span style="color: #000000;">, result: {docs}})
})
})
</span><span style="color: #008000;">/*</span><span style="color: #008000;"> 新增一个类别 </span><span style="color: #008000;">*/</span><span style="color: #000000;">
app.post(</span><span style="color: #800000;">'</span><span style="color: #800000;">/categories</span><span style="color: #800000;">'</span>, adminAuth, (req, res) =><span style="color: #000000;"> {
</span><span style="color: #0000ff;">new</span> Category(req.body).save((err, doc) =><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({code: <span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err})
doc.populate({path:</span><span style="color: #800000;">'</span><span style="color: #800000;">posts</span><span style="color: #800000;">'</span>,<span style="color: #0000ff;">select</span>:<span style="color: #800000;">'</span><span style="color: #800000;">title</span><span style="color: #800000;">'</span>}, (err, doc) =><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({code:<span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err})
</span><span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">200</span>).json({code: <span style="color: #800080;">1</span>, message: <span style="color: #800000;">'</span><span style="color: #800000;">新增成功</span><span style="color: #800000;">'</span><span style="color: #000000;">, result: {doc}})
})
})
})
...</span></pre>
</div>
<p> 在对文章的操作中,则需要显示出类别category的number属性</p>
<div class="cnblogs_code">
<pre><span style="color: #008000;">/*</span><span style="color: #008000;"> 按照id加载一篇文章 </span><span style="color: #008000;">*/</span><span style="color: #000000;">
app.</span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">'</span><span style="color: #800000;">/posts/:id</span><span style="color: #800000;">'</span>, (req, res) =><span style="color: #000000;"> {
Post.findById(req.</span><span style="color: #0000ff;">params</span>.id).populate(<span style="color: #800000;">'</span><span style="color: #800000;">category</span><span style="color: #800000;">'</span>,<span style="color: #800000;">'</span><span style="color: #800000;">number</span><span style="color: #800000;">'</span>).exec((err, doc) =><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({code:<span style="color: #800080;">0</span><span style="color: #000000;">, message:err.message, err})
</span><span style="color: #0000ff;">if</span> (doc === <span style="color: #0000ff;">null</span>) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">404</span>).json({code:<span style="color: #800080;">0</span>, message:<span style="color: #800000;">'</span><span style="color: #800000;">文章不存在</span><span style="color: #800000;">'</span><span style="color: #000000;">})
</span><span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">200</span>).json({code:<span style="color: #800080;">1</span>, message:<span style="color: #800000;">'</span><span style="color: #800000;">获取文章成功</span><span style="color: #800000;">'</span><span style="color: #000000;">, result:{doc}})
})
})
</span><span style="color: #008000;">/*</span><span style="color: #008000;"> 加载所有文章 </span><span style="color: #008000;">*/</span><span style="color: #000000;">
app.</span><span style="color: #0000ff;">get</span>(<span style="color: #800000;">'</span><span style="color: #800000;">/posts</span><span style="color: #800000;">'</span>, (req, res) =><span style="color: #000000;"> {
Post.find().</span><span style="color: #0000ff;">select</span>(<span style="color: #800000;">"</span><span style="color: #800000;">title likes comments recommend imgUrl index</span><span style="color: #800000;">"</span>).populate(<span style="color: #800000;">'</span><span style="color: #800000;">category</span><span style="color: #800000;">'</span>,<span style="color: #800000;">'</span><span style="color: #800000;">number</span><span style="color: #800000;">'</span>).sort(<span style="color: #800000;">"</span><span style="color: #800000;">-createdAt</span><span style="color: #800000;">"</span>).exec((err, docs) =><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({code: <span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err})
</span><span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">200</span>).json({code: <span style="color: #800080;">1</span>, message: <span style="color: #800000;">'</span><span style="color: #800000;">获取文章成功</span><span style="color: #800000;">'</span><span style="color: #000000;">, result: {docs}})
})</span></pre>
</div>
<p> 在新增、更新和删除文章的操作中,都需要重建与category的关联</p>
<div class="cnblogs_code">
<pre><span style="color: #008000;">//</span><span style="color: #008000;"> 关联category的posts数组</span>
fnRelatedCategory = _id =><span style="color: #000000;"> {
Category.findById(_id).exec((err, categoryDoc) </span>=><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({ code: <span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err })
</span><span style="color: #0000ff;">if</span> (categoryDoc === <span style="color: #0000ff;">null</span>) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">404</span>).json({code:<span style="color: #800080;">0</span>, message:<span style="color: #800000;">'</span><span style="color: #800000;">该类别不存在,请刷新后再试</span><span style="color: #800000;">'</span><span style="color: #000000;">})
Post.find({ category: _id }).exec((err, postsDocs) </span>=><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({ code: <span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err })
categoryDoc.posts </span>= postsDocs.map(t =><span style="color: #000000;"> t._id)
categoryDoc.save(err </span>=><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({ code: <span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err })
})
})
})
}
</span><span style="color: #008000;">/*</span><span style="color: #008000;"> 按照id更新一篇文章 </span><span style="color: #008000;">*/</span><span style="color: #000000;">
app.put(</span><span style="color: #800000;">'</span><span style="color: #800000;">/posts/:id</span><span style="color: #800000;">'</span>, adminAuth, (req, res) =><span style="color: #000000;"> {
Post.findById(req.</span><span style="color: #0000ff;">params</span>.id).exec((err, doc) =><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({code: <span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err})
</span><span style="color: #0000ff;">if</span> (doc === <span style="color: #0000ff;">null</span>) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">404</span>).json({code: <span style="color: #800080;">0</span>, message: <span style="color: #800000;">'</span><span style="color: #800000;">文章不存在,请刷新后再试</span><span style="color: #800000;">'</span><span style="color: #000000;">})
</span><span style="color: #0000ff;">for</span> (prop <span style="color: #0000ff;">in</span><span style="color: #000000;"> req.body) {
doc </span>=<span style="color: #000000;"> req.body
}
doc.save((err) </span>=><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({code: <span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err})
doc.populate({path:</span><span style="color: #800000;">'</span><span style="color: #800000;">category</span><span style="color: #800000;">'</span>,<span style="color: #0000ff;">select</span>:<span style="color: #800000;">'</span><span style="color: #800000;">number</span><span style="color: #800000;">'</span>}, (err, doc) =><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (err) <span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">500</span>).json({code:<span style="color: #800080;">0</span><span style="color: #000000;">, message: err.message, err})
fnRelatedCategory(doc.category._id)
</span><span style="color: #0000ff;">return</span> res.status(<span style="color: #800080;">200</span>).json({code: <span style="color: #800080;">1</span>, message: <span style="color: #800000;">'</span><span style="color: #800000;">更新成功</span><span style="color: #800000;">'</span><span style="color: #000000;">, result: {doc}})
})
})
})
})
...</span></pre>
</div>
<p> </p>
<h2>最后</h2>
<p> mongoose操作基础入门大致就是以上这些。mongoose的很多操作与mongodb的操作命令非常类似,学起来并不难。但是,由于中文资源并不完善,需要对照英文文档进行学习,可能会稍显吃力。而且,mongoose对mongodb做了许多扩展,增加了许多方法,需要更多耐心</p>
<p> 欢迎交流</p>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
<p><span>好的代码像粥一样,都是用时间熬出来的</span></p>
<img src="https://pic.xiaohuochai.site/blog/qrcode.jpg" alt="二维码"><br><br>
来源:https://www.cnblogs.com/xiaohuochai/p/7215067.html
頁:
[1]