0. 前言:
Mongoose是NodeJS的驅動,不能作為其他語言的驅動。Mongoose有兩個特點:
- 通過關系型數據庫的思想來設計非關系型數據庫
- 基於mongodb驅動,簡化操作
Mongooose中,有三個比較重要的概念,分別是Schema、Model、Document。它們的關系是:Schema生成Model,Model創造Document,Model和Document都可對數據庫操作造成影響,但Model比Document更具操作性。
Schema
用於定義數據庫的結構。類似創建表時的數據定義(不僅僅可以定義文檔的結構和屬性,還可以定義文檔的實例方法、靜態模型方法、復合索引等),每個Schema
會映射到mongodb中的一個collection,Schema
不具備操作數據庫的能力。
Model是由Schema編譯而成的構造器,具有抽象屬性和行為,可以對數據庫進行增刪查改。Model的每一個實例(instance)就是一個文檔document。
Document是由Model創建的實體,它的操作也會影響數據庫。
1. 安裝
在此之前需要安裝nodejs和mongodb,才能使用npm來安裝mongoose
npm install mongoose
項目中可使用下面的命令安裝mongoose並自動將其添加到依賴
npm i mongoose --save
2. 連接數據庫
2.1 首先使用 require() 引入mongoose
var mongoose = require('mongoose');
2.2 使用 connect() 來連接mongodb數據庫
mongoose.connect(url);
connect()最簡單的使用方式,就是只要傳入url參數即可,如下所示。
/*直接連接*/ mongoose.connect("mongodb://127.0.0.1/mongoose_test" ); /*傳遞用戶名密碼來連接*/ mongoose.connect('mongodb://username:password@host:port/database?options...');
注意:mongoose版本大於或等於4.11.0時,連接數據庫會提示warning(不影響運行),避免的方法添加userMongoClient的設置,且屬性值為true
mongoose.connect('mongodb://數據庫的ip地址:端口號/數據庫名', { useMongoClient: true});
connect()方法還接受一個選項對象options,該對象將傳遞給底層驅動程序。
mongoose.connect(uri, options);
可用選項如下所示,更多詳見參考,options 所包含的所有選項優先於連接字符串中傳遞的選項
db -數據庫設置 server -服務器設置 replset -副本集設置 user -用戶名 pass -密碼 auth -鑒權選項 mongos -連接多個數據庫
如果要連接多個數據庫,只需要設置多個url以,
隔開,同時設置mongos
為true
mongoose.connect('urlA,urlB,...', { mongos : true })
connect()函數還接受一個回調參數,來判斷是否連接成功
mongoose.connect(uri, options, function(error) { });
var mongoose = require('mongoose'); mongoose.connect("mongodb://localhost/mongoose_test", function(err) { if(err){ console.log('連接失敗'); }else{ console.log('連接成功'); } });
2.3 使用 disconnect() 斷開數據庫連接(一般不需要調用)
MongoDB數據庫,一般情況下,只需要連接一次,連接一次以后,除非項目停止服務器關閉,否則連接一般不會斷開
mongoose.disconnect();
2.4 監聽MongoDB數據庫的連接狀態
在mongoose對象中,有一個屬性叫做connection,該對象表示的就是數據庫連接。通過監視該對象的狀態,可以來監聽數據庫的連接與斷開
數據庫連接成功的事件
mongoose.connection.once("open",function(){});
數據庫斷開的事件
mongoose.connection.once("close",function(){});
3. Schema
Schema主要用於定義MongoDB中集合Collection里文檔document的結構。
定義Schema需要指定字段名和類型,支持的類型包括以下9種
String 字符串
Number 數字
Date 日期
Buffer 二進制
Boolean 布爾值
Mixed 混合類型
ObjectId 對象ID
Array 數組
Decimal128 Decimal類型
通過mongoose.Schema來調用Schema,然后使用new方法來創建schema對象
var mongoose = require("mongoose"); mongoose.connect("mongodb://127.0.0.1/mongoose_test",{useMongoClient:true}); mongoose.connection.once("open",function () { console.log("數據庫連接成功~~~"); }); //將mongoose.Schema 賦值給一個變量 var Schema = mongoose.Schema; //創建Schema(模式)對象 var stuSchema = new Schema({ name:String, age:Number, gender:{ type:String, default:"female" }, address:String });
[注意]創建Schema對象時,聲明字段類型有兩種方法,一種是首字母大寫的字段類型,另一種是引號包含的小寫字段類型
var mySchema = new Schema({title:String, author:String}); //或者 var mySchema = new Schema({title:'string', author:'string'});
如果需要在Schema定義后添加其他字段,可以使用add()方法
var MySchema = new Schema; MySchema.add({ name: 'string', color: 'string', price: 'number' });
4. Model & Document
模型Model是根據Schema編譯出的構造器,或者稱為類,通過Model可以實例化出文檔對象document。文檔document的創建和檢索都需要通過模型Model來處理
mongoose.model();
[注意]一定要將model()方法的第一個參數和其返回值設置為相同的值,否則會出現不可預知的結果
Mongoose會將集合名稱設置為模型名稱的小寫版。如果名稱的最后一個字符是字母,則會變成復數;如果名稱的最后一個字符是數字,則不變;如果模型名稱為"MyModel",則集合名稱為"mymodels";如果模型名稱為"Model1",則集合名稱為"model1"。
實例化文檔document
var StuModel = mongoose.model("student" , stuSchema); //Document 和 集合中的文檔一一對應 , Document是Model的實例 通過Model查詢到結果都是Document //創建一個Document var stu = new StuModel({ name:"孫悟空", age:18, gender:"male", address:"花果山" });
文檔保存
通過new StuModel()創建的文檔stu,必須通過save()方法,才能將創建的文檔保存到數據庫的集合中,集合名稱為模型名稱的小寫復數版
//回調函數是可選項,第一個參數為err,第二個參數為保存的文檔對象 save(function (err, doc) {})
stu.save(function (err) { if (err) return handleError(err); })
也可減少步驟,直接向數據庫插入文檔
var StuModel = mongoose.model("student" , stuSchema); //向數據庫中插入一個文檔 //StuModel.create(doc, function(err){}); StuModel.create({ name:"白骨精", age:16, address:"白骨洞" },function (err) { if(!err){ console.log("插入成功~~~"); } });
結果
5. Model對象的方法
有了Model,我們就可以來對數據庫進行增刪改查的操作了。具體方法可參考官方文檔。
5.1 增加方法
Model.create(doc(s), [callback]) - 用來創建一個或多個文檔並添加到數據庫中 - 參數: doc(s) 可以是一個文檔對象,也可以是一個文檔對象的數組 callback 當操作完成以后調用的回調函數
StuModel.create([ { name:"沙和尚", age:38, gender:"male", address:"流沙河" } ],function (err) { if(!err){ console.log(arguments); } });
控制台輸出
5.2 修改方法
Model.update(conditions, doc, [options], [callback]) Model.updateMany(conditions, doc, [options], [callback]) Model.updateOne(conditions, doc, [options], [callback]) - 用來修改一個或多個文檔 - 參數: conditions 查詢條件 doc 修改后的對象 options 配置參數 callback 回調函數 Model.replaceOne(conditions, doc, [options], [callback])
StuModel.updateOne({name:"唐僧"},{$set:{age:20}},function (err) { if(!err){ console.log("修改成功"); } });
5.3 查詢方法
Model.find(conditions, [projection], [options], [callback]) - 查詢所有符合條件的文檔 總會返回一個數組 Model.findById(id, [projection], [options], [callback]) - 根據文檔的id屬性查詢文檔 Model.findOne([conditions], [projection], [options], [callback]) - 查詢符合條件的第一個文檔 總會返回一個具體的文檔對象(非數組) conditions 查詢的條件 projection 投影 需要獲取到的字段 - 兩種方式 {name:1,_id:0} "name -_id" options 查詢選項(skip limit) {skip:3 , limit:1} callback 回調函數,查詢結果會通過回調函數返回 回調函數必須傳,如果不傳回調函數,壓根不會查詢
官方文檔查詢方法截圖如下
下面分別演示幾種不同的查詢方法
//查詢name為“唐僧”的 StuModel.find({name:"唐僧"},function (err , docs) { if(!err){ console.log(docs); } });
結果
//只查詢name,且不查詢_id (_id字段默認輸出) StuModel.find({},{name:1 , _id:0},function (err , docs) { if(!err){ console.log(docs); } });
結果
//只查詢文檔的name,age值,查詢時跳過3個,結果集限制只查詢出一個 StuModel.find({},"name age -_id", {skip:3 , limit:1} , function (err , docs) { if(!err){ console.log(docs); } });
結果
StuModel.findOne({} , function (err , doc) { if(!err){ console.log(doc); } });
結果
StuModel.findById("59c4c3cf4e5483191467d392" , function (err , doc) { if(!err){ //console.log(doc); //通過find()查詢的結果,返回的對象,就是Document,文檔對象 //Document對象是Model的實例 console.log(doc instanceof StuModel); } });
結果
5.4 刪除方法
Model.remove(conditions, [callback])
Model.deleteOne(conditions, [callback])
Model.deleteMany(conditions, [callback])
StuModel.remove({name:"白骨精"},function (err) { if(!err){ console.log("刪除成功~~"); } });
5.5 統計
Model.count(conditions, [callback])
- 統計文檔的數量的
StuModel.count({},function (err , count) { if(!err){ console.log(count); } });
6. Document對象的方法
Document 和 集合中的文檔一一對應,Document是Model的實例。通過Model查詢到結果都是Document。
6.1 保存
save([options], [options.safe], [options.validateBeforeSave], [fn])
//創建一個Document var stu = new StuModel({ name:"奔波霸", age:48, gender:"male", address:"碧波潭" }); //保存改document對象 stu.save(function (err,product,numAffected) { //返回三個對象 err:失敗信息; product:保存的對象; numAffected:該document對象被持久化了為1,否則為0 if(!err){ console.log("保存成功~~~"); }
6.2 更新
update(update,[options],[callback])
doc.update({$set:{age:28}},function (err) { if(!err){ console.log("修改成功~~~"); } });
或者對document對象進行修改,再執行save()方法
doc.age = 28;
doc.save();
6.3 刪除
remove([callback])
doc.remove(function (err) { if(!err){ console.log("刪除成功~~~"); } });
6.4 其他
get(name) - 獲取文檔中的指定屬性值 set(name , value) - 設置文檔的指定的屬性值 id - 獲取文檔的_id屬性值 toJSON() ****** - 轉換為一個JSON對象 toObject() - 將Document對象轉換為一個普通的JS對象【轉換為普通的js對象以后,注意所有的Document對象的方法或屬性都不能使用了】
console.log(doc.get("age")); console.log(doc.age); doc.set("name","豬九戒"); doc.name = "hahaha"; console.log(doc._id); var j = doc.toJSON(); console.log(j); var o = doc.toObject(); console.log(o); doc = doc.toObject(); delete doc.address; console.log(doc._id);
參考: