mongoose入門
MongoDB是一個(gè)開源的NoSQL數(shù)據(jù)庫(kù)椭蹄,相比MySQL那樣的關(guān)系型數(shù)據(jù)庫(kù)巫财,它更顯得輕巧杨何、靈活酱塔,非常適合在數(shù)據(jù)規(guī)模很大、事務(wù)性不強(qiáng)的場(chǎng)合下使用危虱。同時(shí)它也是一個(gè)對(duì)象數(shù)據(jù)庫(kù)羊娃,沒有表、行等概念埃跷,也沒有固定的模式和結(jié)構(gòu)迁沫,所有的數(shù)據(jù)以文檔的形式存儲(chǔ)(文檔,就是一個(gè)關(guān)聯(lián)數(shù)組式的對(duì)象捌蚊,它的內(nèi)部由屬性組成,一個(gè)屬性對(duì)應(yīng)的值可能是一個(gè)數(shù)近弟、字符串缅糟、日期、數(shù)組祷愉,甚至是一個(gè)嵌套的文檔窗宦。)赦颇,數(shù)據(jù)格式就是JSON。
假定讀者已經(jīng)了解了mongdb和mysql的區(qū)別和為什么選用mongodb赴涵,繼而介紹nodejs里的mongoose模塊進(jìn)行實(shí)戰(zhàn)媒怯,具體分4步驟
- mongoose是什么?
- mongoose入門
- mongoose概念
- mongoose crud
Mongoose是什么髓窜?
Mongoose是MongoDB的一個(gè)對(duì)象模型工具扇苞,是基于node-mongodb-native開發(fā)的MongoDB nodejs驅(qū)動(dòng),可以在異步的環(huán)境下執(zhí)行寄纵。同時(shí)它也是針對(duì)MongoDB操作的一個(gè)對(duì)象模型庫(kù)鳖敷,封裝了MongoDB對(duì)文檔的的一些增刪改查等常用方法,讓NodeJS操作Mongodb數(shù)據(jù)庫(kù)變得更加靈活簡(jiǎn)單程拭。
Mongoose定踱,因?yàn)榉庋b了對(duì)MongoDB對(duì)文檔操作的常用處理方法,可以高效的操作mongodb,同時(shí)可以理解mongoose是一個(gè)簡(jiǎn)易版的orm 恃鞋,提供了類似schema定義崖媚,hook、plugin恤浪、virtual畅哑、populate等機(jī)制,讓NodeJS操作Mongodb數(shù)據(jù)庫(kù)變得特別簡(jiǎn)單!
以往書中往往直接上例子资锰,混合各種庫(kù)和代碼敢课,容易讓人暈,必須在例子中才能知道m(xù)是如何使用的绷杜,我一直認(rèn)為這是不合理的直秆,為什么我要掌握其他的知識(shí)才能學(xué)mongoose?
其實(shí)鞭盟,它也僅僅是一個(gè)node模塊而已圾结。
官網(wǎng):http://mongoosejs.com/
mongoose入門
前面我們已經(jīng)認(rèn)識(shí)了Mongoose,也了解了MongoDB齿诉,回顧一下:MongoDB是一個(gè)對(duì)象數(shù)據(jù)庫(kù)筝野,是用來存儲(chǔ)數(shù)據(jù)的;Mongoose是封裝了MongoDB操作的一個(gè)對(duì)象模型庫(kù),是用來操作這些數(shù)據(jù)的粤剧。
好歇竟,下面我們就來進(jìn)行操作數(shù)據(jù)的第一步吧。
準(zhǔn)備
1抵恋、 安裝mongoose
$ npm install --save mongoose
2焕议、 引用mongoose
var mongoose = require("mongoose");
3、 使用"mongoose"連接數(shù)據(jù)庫(kù)
var db = mongoose.connect("mongodb://user:pass@ip:port/database");
說明
- user 是mongodb里用戶名
- pass 是mongodb里用戶對(duì)應(yīng)的密碼
- ip 是mongodb服務(wù)器可以訪問
ip
地址弧关,比如本地為127.0.0.1
- port 是mongodb服務(wù)器可以訪問端口盅安,默認(rèn)是
27017
測(cè)試
執(zhí)行下面代碼檢查默認(rèn)數(shù)據(jù)庫(kù)test唤锉,是否可以正常連接成功?
var mongoose = require("mongoose");
var db = mongoose.connect("mongodb://127.0.0.1:27017/db_helloworld");
db.connection.on("error", function (error) {
console.log("數(shù)據(jù)庫(kù)連接失敗:" + error);
});
db.connection.on("open", function () {
console.log("數(shù)據(jù)庫(kù)連接成功");
});
執(zhí)行代碼
$ node book-source/db/helloworld/connect.js
數(shù)據(jù)庫(kù)連接成功
當(dāng)mongodb沒有啟動(dòng)的時(shí)候會(huì)報(bào)錯(cuò)别瞭,當(dāng)出現(xiàn)如下問題窿祥,請(qǐng)執(zhí)行mhg
啟動(dòng)mongodb即可
$ node book-source/db/helloworld/connect.js
數(shù)據(jù)庫(kù)連接失敗:MongoError: connect ECONNREFUSED 127.0.0.1:27017
最小demo
這里給出極簡(jiǎn)demo蝙寨,用于講解mongoose從連接數(shù)據(jù)庫(kù)到對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作完整過程晒衩,這樣更容易讓讀者了解核心原理,代碼如下:
// 1籽慢、引入`mongoose`模塊
var mongoose = require('mongoose');
// 2浸遗、通過`mongoose.connect`連接mongodb數(shù)據(jù)庫(kù)
mongoose.connect('mongodb://127.0.0.1/db_helloworld');
// 3、通過`mongoose.model`定義模型(model)
var Cat = mongoose.model('Cat', { name: String });
// 4箱亿、通過`new`關(guān)鍵字實(shí)例化Cat模型跛锌,參數(shù)是`{ name: 'Zildjian' }`,創(chuàng)建kitty對(duì)象
var kitty = new Cat({ name: 'Zildjian' });
// 5届惋、執(zhí)行`kitty.save`來保存到數(shù)據(jù)庫(kù)
kitty.save(function (err) {
if (err) {
console.log('save error:' + err);
}
console.log('save sucess');
});
核心步驟說明
- 定義模型(model)
- 通過
new
關(guān)鍵字實(shí)例化Cat模型髓帽,創(chuàng)建kitty對(duì)象 - 執(zhí)行
kitty.save
來保存到數(shù)據(jù)庫(kù)
這個(gè)其實(shí)就是mongoose最常見的用法,首先約定schema脑豹,即在模型model定義的時(shí)候指定字段和字段類型郑藏,避免亂用schema-free問題。之后對(duì)實(shí)例化模型創(chuàng)建的對(duì)象進(jìn)行操作瘩欺,完成我們常見的增刪改查功能必盖。
模型(model)定義即定義對(duì)象,對(duì)象操作即對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作
執(zhí)行如下
$ node book-source/db/helloworld/helloworld.js
如無錯(cuò)誤日志俱饿,即代表數(shù)據(jù)保存成功歌粥。此時(shí)打開robo mongodb客戶端查看一下具體數(shù)據(jù)是否保存成功。
創(chuàng)建robo客戶端連接
[圖片上傳失敗...(image-a2a818-1519355504563)]
查看cat數(shù)據(jù)
[圖片上傳失敗...(image-a49fdc-1519355504563)]
如果有{ name: 'Zildjian' }
記錄的拍埠,即為正常失驶。
實(shí)例
- 連接數(shù)據(jù)庫(kù)信息放到獨(dú)立文件里
- 模型定義放到獨(dú)立文件
- 在具體調(diào)用的文件里,使用模型定義
連接數(shù)據(jù)庫(kù)
看一下實(shí)際代碼枣购,db/mini/connect.js
var mongoose = require("mongoose");
var db = mongoose.connect("mongodb://127.0.0.1:27017/db_helloworld");
db.connection.on("error", function (error) {
console.log("數(shù)據(jù)庫(kù)連接失旀姨健:" + error);
});
db.connection.on("open", function () {
console.log("數(shù)據(jù)庫(kù)連接成功");
});
一般項(xiàng)目里,所有模型都共用一個(gè)數(shù)據(jù)庫(kù)連接信息棉圈,所以把連接數(shù)據(jù)庫(kù)的代碼抽取到connect.js
里涩堤,然后在對(duì)應(yīng)的模型里會(huì)app入口引用即可。
模型定義
看一下實(shí)際模型定義代碼分瘾,db/mini/user.js
var mongoose = require('mongoose');
// 定義Schema
UserSchema = new mongoose.Schema({
username: {// 真實(shí)姓名
type: String,
required: true
},
password: { // 密碼
type: String,
required: true
}
});
// 定義Model
var UserModel = mongoose.model('User', UserSchema);
// 暴露接口
module.exports = UserModel;
這是MVC里Model層最長(zhǎng)見的代碼定躏,沒有連接信息,也沒有其他額外不相干代碼,當(dāng)你看到user.js
你就能理解它在數(shù)據(jù)庫(kù)里對(duì)應(yīng)的表結(jié)構(gòu)痊远,以及字段的類型、約束等信息氏捞,一般來說碧聪,代碼寫的越干凈,可讀性會(huì)更好一些液茎。
這里定義的User模型里只有 用戶名
和 密碼
2個(gè)字段逞姿,它們都必須有值的,也就是說當(dāng)你創(chuàng)建用戶的時(shí)候捆等,沒有密碼或者沒有用戶名你是無法創(chuàng)建成功的滞造。
測(cè)試代碼
看一下實(shí)際代碼db/mini/user.js
// 1、引入`mongoose connect`
require('./connect');
// 2栋烤、引入`User` Model
var User = require('./user');
// 3谒养、定義`user` Entity
var user = new User({
username: 'i5ting',
password: '0123456789'
});
// 4、對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作
user.save(function(err, doc){
if (err) {
console.log('save error:' + err);
}
console.log('save sucess \n' + doc);
})
核心步驟
- 引入數(shù)據(jù)庫(kù)連接明郭,保證mongodb已經(jīng)連接成功
- 引入模型(model)定義文件买窟,即文檔(表)結(jié)構(gòu)定義
- 實(shí)例化UserModel,創(chuàng)建user實(shí)體
- 最后通過user實(shí)體對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作薯定,完成用戶注冊(cè)功能始绍。
這是項(xiàng)目里數(shù)據(jù)訪問層的代碼,它真實(shí)的對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作话侄,所以它一般會(huì)出現(xiàn)在controller
或service
層亏推。
執(zhí)行測(cè)試
$ node db/mini/test.js
數(shù)據(jù)庫(kù)連接成功
save sucess
{ _id: 57341fc54d97ee0249082a1d,
password: '0123456789',
username: 'i5ting',
__v: 0 }
概念
結(jié)合上面的實(shí)例來講4個(gè)核心概念,以便于理解
- ORM 對(duì)象關(guān)系映射
- Schema
- Model 模型
- Entity 實(shí)體
對(duì)象關(guān)系映射
對(duì)象關(guān)系映射(英語(yǔ):Object Relational Mapping年堆,簡(jiǎn)稱ORM篇亭,或O/RM柔昼,或O/R mapping),是一種程序設(shè)計(jì)技術(shù),用于實(shí)現(xiàn)面向?qū)ο缶幊陶Z(yǔ)言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換。從效果上說几莽,它其實(shí)是創(chuàng)建了一個(gè)可在編程語(yǔ)言里使用的“虛擬對(duì)象數(shù)據(jù)庫(kù)”。如今已有很多免費(fèi)和收費(fèi)的ORM產(chǎn)品洒忧,而有些程序員更傾向于創(chuàng)建自己的ORM工具蛉抓。
面向?qū)ο笫菑能浖こ袒驹瓌t(如耦合笑跛、聚合陈哑、封裝)的基礎(chǔ)上發(fā)展起來的纠屋,而關(guān)系數(shù)據(jù)庫(kù)則是從數(shù)學(xué)理論發(fā)展而來的涂臣,兩套理論存在顯著的區(qū)別。為了解決這個(gè)不匹配的現(xiàn)象售担,對(duì)象關(guān)系映射技術(shù)應(yīng)運(yùn)而生。
對(duì)象關(guān)系映射(Object-Relational Mapping)提供了概念性的署辉、易于理解的模型化數(shù)據(jù)的方法族铆。
ORM方法論基于三個(gè)核心原則:
- 簡(jiǎn)單:以最基本的形式建模數(shù)據(jù)。
- 傳達(dá)性:數(shù)據(jù)庫(kù)結(jié)構(gòu)被任何人都能理解的語(yǔ)言文檔化哭尝。
- 精確性:基于數(shù)據(jù)模型創(chuàng)建正確標(biāo)準(zhǔn)化的結(jié)構(gòu)哥攘。
典型地,建模者通過收集來自那些熟悉應(yīng)用程序但不熟練的數(shù)據(jù)建模者的人的信息開發(fā)信息模型材鹦。建模者必須能夠用非技術(shù)企業(yè)專家可以理解的術(shù)語(yǔ)在概念層次上與數(shù)據(jù)結(jié)構(gòu)進(jìn)行通訊逝淹。建模者也必須能以簡(jiǎn)單的單元分析信息,對(duì)樣本數(shù)據(jù)進(jìn)行處理桶唐。ORM專門被設(shè)計(jì)為改進(jìn)這種聯(lián)系栅葡。
讓我們從O/R開始。字母O起源于 對(duì)象(OBJECT),而R則來自于 關(guān)系(RELATIONAL)尤泽。幾乎所有的程序里面欣簇,都存在對(duì)象和關(guān)系數(shù)據(jù)庫(kù)。在業(yè)務(wù)邏輯層和用戶界面層中坯约,我們是面向?qū)ο蟮男苎省.?dāng)對(duì)象信息發(fā)生變化的時(shí)候,我們需要把對(duì)象的信息保存在關(guān)系數(shù)據(jù)庫(kù)中闹丐。
最簡(jiǎn)單的理解:
ORM是讓用語(yǔ)言中的對(duì)象來操作數(shù)據(jù)庫(kù)横殴,至于如何實(shí)現(xiàn)就是orm工具實(shí)現(xiàn)的,可以理解mongoose是orm工具卿拴。
mongoose包括以下四部分:
- 一個(gè)對(duì)持久類對(duì)象進(jìn)行CRUD操作的API衫仑,可以理解為實(shí)體Entity上的方法
- 一個(gè)語(yǔ)言或API用來規(guī)定與類和類屬性相關(guān)的查詢,比如Population
- 一個(gè)規(guī)定MAPPING METADATA的工具巍棱,可以理解為Schema定義
- 一種技術(shù)可以讓ORM的實(shí)現(xiàn)各種db操作的封裝
Schema
Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.
Schema是一種以文件形式存儲(chǔ)的數(shù)據(jù)庫(kù)模型骨架惑畴,無法直接通往數(shù)據(jù)庫(kù)端,也就是說它不具備對(duì)數(shù)據(jù)庫(kù)的操作能力航徙,僅僅只是定義數(shù)據(jù)庫(kù)模型在程序片段中的一種表現(xiàn)如贷,可以說是數(shù)據(jù)屬性模型(傳統(tǒng)意義的表結(jié)構(gòu)),又或著是“集合”的模型骨架。
最簡(jiǎn)單的理解:
Schema是對(duì)文檔(表)結(jié)構(gòu)的定義
那如何去定義一個(gè)Schema呢杠袱,請(qǐng)看示例:
// 定義Schema
UserSchema = new mongoose.Schema({
username: {// 真實(shí)姓名
type: String,
required: true
},
password: { // 密碼
type: String,
required: true
}
});
基本屬性類型有:字符串尚猿、日期型、數(shù)值型楣富、布爾型(Boolean)凿掂、null、數(shù)組纹蝴、內(nèi)嵌文檔等庄萎,當(dāng)然它還有更豐富的對(duì)字段進(jìn)行校驗(yàn)約束的功能。
模型(Model)
Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retrieved from our database. All document creation and retrieval from the database is handled by these models.
模型(Model)是由Schema構(gòu)造生成的模型塘安,除了Schema定義的數(shù)據(jù)庫(kù)骨架以外糠涛,還具有數(shù)據(jù)庫(kù)操作的行為,類似于管理數(shù)據(jù)庫(kù)屬性兼犯、行為的類忍捡。
如何通過Schema來創(chuàng)建Model呢,如下示例:
var db = mongoose.connect("mongodb://127.0.0.1:27017/test");
// 創(chuàng)建Model
var TestModel = db.model("test1", TestSchema);
// 定義Model
var UserModel = mongoose.model('User', UserSchema);
User
是模型名稱切黔,它對(duì)應(yīng)到mongodb里就是數(shù)據(jù)庫(kù)中的集合名稱砸脊,默認(rèn)會(huì)轉(zhuǎn)成復(fù)數(shù),變?yōu)?users',當(dāng)我們對(duì)其添加數(shù)據(jù)時(shí)如果users
已經(jīng)存在纬霞,則會(huì)保存到其目錄下凌埂,如果未存在,則會(huì)創(chuàng)建users集合险领,然后在保存數(shù)據(jù)侨舆。
擁有了Model,我們也就擁有了操作數(shù)據(jù)庫(kù)的金鑰匙绢陌,在后面的內(nèi)容中挨下,我們就會(huì)學(xué)習(xí)使用Model來進(jìn)行增刪改查的具體操作,所以脐湾,一定要熟悉他的創(chuàng)建格式喲臭笆!
如果你想對(duì)某個(gè)集合有所作為,那就交給Model模型來處理吧秤掌,創(chuàng)建一個(gè)Model模型愁铺,我們需要指定:1.集合名稱,2.集合的Schema結(jié)構(gòu)對(duì)象闻鉴,滿足這兩個(gè)條件茵乱,我們就會(huì)擁有一個(gè)操作數(shù)據(jù)庫(kù)的金鑰匙。
實(shí)體(Entity)
Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.
實(shí)體(Entity)是由Model創(chuàng)建的實(shí)體孟岛,使用save方法保存數(shù)據(jù)瓶竭,Model和Entity都有能影響數(shù)據(jù)庫(kù)的操作督勺,但Model比Entity更具操作性。
使用Model創(chuàng)建Entity斤贰,如下示例:
var user = new User({
username: 'i5ting',
password: '0123456789'
});
console.log(user.username); // i5ting
console.log(user.password); //0123456789
創(chuàng)建成功之后智哀,Schema屬性就變成了Model和Entity的公共屬性了。
總結(jié)
Schema是骨架荧恍,模型(model)是根據(jù)Schema創(chuàng)建的模板瓷叫,也就是說Schema和Model是定義部分,而實(shí)體Entity是模型實(shí)例化后創(chuàng)建的對(duì)象送巡,它才是真正對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作的摹菠。
所以我們會(huì)把定義部分(Schema + model)和實(shí)體操作部分(Entity)分開,定義是不變的骗爆,而實(shí)體是對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作辨嗽,操作類是術(shù)語(yǔ)可變的,所以在mvc分層的時(shí)候model實(shí)際放的是定義部分淮腾,而在controller里使用的是實(shí)體操作部分的。
基于前面的內(nèi)容屉佳,接下來我們就開始學(xué)習(xí)對(duì)數(shù)據(jù)的具體操作了谷朝,下面是關(guān)于一些基礎(chǔ)數(shù)據(jù)的定義,相信對(duì)于你來說已經(jīng)不陌生了武花,請(qǐng)?jiān)谧屑?xì)溫習(xí)一遍吧圆凰!
CRUD(增刪改查)
CRUD為數(shù)據(jù)庫(kù)的最常見的4種基本操作,即增加(Create)体箕、讀取(Retrieve)(重新得到數(shù)據(jù))专钉、更新(Update)和刪除(Delete)幾個(gè)單詞的首字母簡(jiǎn)寫。主要被用在描述軟件系統(tǒng)中數(shù)據(jù)庫(kù)或者持久層的基本操作功能累铅。
mongoose提供如下的crud方法
- save
- find | findOne
- update
- remove
下面我們使用user模型為例跃须,給出具體例子
增加(Create)
文檔
Model#save(product,)
@description Saves this document.
Parameters:
- product, <function(err, > Number)} [fn] optional callback
Returns:
<Promise> Promise
具體代碼
const user = new User({
username: 'i5ting',
password: '0123456789'
});
user.save((err, u) => {
t.false(err);
t.is(u.username, 'i5ting');
});
讀取(Retrieve)
find:根據(jù)條件查詢,返回的是數(shù)組
文檔
Model.find(conditions, [fields], [options], [callback])
Finds documents
Parameters:
- conditions <Object>
- [fields] <Object> optional fields to select
- [options] <Object> optional
- [callback] <Function>
Returns:
<Query>
代碼
User.find({}, (err, docs) => {
t.false(err);
t.is(docs.length, 1);
t.is(docs[0].username, 'i5ting');
});
findOne:根據(jù)條件查詢娃兽,返回的是一條數(shù)據(jù)對(duì)象
文檔
Model.findOne([conditions], [fields], [options], [callback])
Finds one document.
Parameters:
- [conditions] <Object>
- [fields] <Object> optional fields to select
- [options] <Object> optional
- [callback] <Function>
Returns:
<Query>
代碼
User.findOne({username: 'i5ting'}, (err, doc) => {
t.false(err);
t.is(doc.length, 1);
t.is(doc.username, 'i5ting');
});
更新(Update)
findByIdAndUpdate:根據(jù)ID查找并更新
文檔說明如下
Model.findByIdAndUpdate(id, [update], [options], [callback])
Issues a mongodb findAndModify update command by a documents id.
show code
Parameters:
- id <ObjectId, HexId> an ObjectId or string that can be cast to one.
- [update] <Object>
- [options] <Object>
- [callback] <Function>
Returns:
<Query>
具體代碼
User.findByIdAndUpdate(u._id, {
username: 'sang',
}, (err, user) => {
t.false(err);
t.is(user.username, 'sang');
});
findOneAndUpdate:根據(jù)查詢條件查找并更新
Model.findOneAndUpdate([conditions], [update], [options], [callback])
Issues a mongodb findAndModify update command.
Parameters:
- [conditions] <Object>
- [update] <Object>
- [options] <Object>
- [callback] <Function>
Returns:
<Query>
具體代碼
User.findOneAndUpdate({
username: 'i5ting for update 2',
}, {
username: 'sang',
}, (err, user) => {
t.false(err);
t.is(user.username, 'sang');
});
刪除(Delete)
文檔
Model.remove(conditions, [callback])
Removes documents from the collection.
Parameters:
- conditions <Object>
- [callback] <Function>
Returns:
<Promise> Promise
代碼
User.remove({username: 'i5ting for delete'}, (err, doc) => {
t.false(err);
t.is(doc.result.ok, 1);
t.is(doc.result.n, 1);
});
執(zhí)行測(cè)試
$ cd db
$ npm test
> koa-db@1.0.0 test /Users/sang/workspace/17koa/book-source/db
> ava crud -v
數(shù)據(jù)庫(kù)連接成功
? #save()
? #find() return array
? #findById() return array
? #findOne() return user obj
? #remove()
? #findByIdAndUpdate()
? #findOneAndUpdate()
6 tests passed
調(diào)試模式
調(diào)試模式是mongoose提供的一個(gè)非常實(shí)用的功能菇民,用于查看mongoose模塊對(duì)mongodb操作的日志,一般開發(fā)時(shí)會(huì)打開此功能投储,以便更好的了解和優(yōu)化對(duì)mongodb的操作第练。
打開調(diào)試的核心代碼是設(shè)置 debug
變量值為 true
即可
var mongoose = require("mongoose");
// 核心代碼,是否開啟測(cè)試
mongoose.set('debug', true);
var db = mongoose.connect("mongodb://127.0.0.1:27017/db_helloworld");
db.connection.on("error", function (error) {
console.log("數(shù)據(jù)庫(kù)連接失斅贶瘛:" + error);
});
db.connection.on("open", function () {
console.log("數(shù)據(jù)庫(kù)連接成功");
});
執(zhí)行測(cè)試如下
$ cd db
$ npm test
> koa-db@1.0.0 test /Users/sang/workspace/17koa/book-source/db
> ava crud -v
數(shù)據(jù)庫(kù)連接成功
Mongoose: users.remove({}) {}
? #save()
? #find() return array
? #findById() return array
? #findOne() return user obj
? #remove()
? #findByIdAndUpdate()
? #findOneAndUpdate()
Mongoose: users.insert({ username: 'i5ting', password: '0123456789', _id: ObjectId("5734490640caa6d36906b8d4"), __v: 0 })
Mongoose: users.find({}) { fields: undefined }
Mongoose: users.findOne({ username: 'i5ting' }) { fields: undefined }
Mongoose: users.insert({ username: 'i5ting for delete', password: '0123456789', _id: ObjectId("5734490640caa6d36906b8d5"), __v: 0 })
Mongoose: users.insert({ username: 'i5ting for update 1', password: '0123456789', _id: ObjectId("5734490640caa6d36906b8d6"), __v: 0 })
Mongoose: users.insert({ username: 'i5ting for update 2', password: '0123456789', _id: ObjectId("5734490640caa6d36906b8d7"), __v: 0 })
Mongoose: users.remove({ username: 'i5ting for delete' }) {}
Mongoose: users.findAndModify({ _id: ObjectId("5734490640caa6d36906b8d6") }) [] { '$set': { username: 'sang' } } { new: false, upsert: false }
Mongoose: users.findAndModify({ username: 'i5ting for update 2' }) [] { '$set': { username: 'sang' } } { new: false, upsert: false }
6 tests passed
總結(jié)
從mongoose是什么娇掏,到如何使用,以及核心概念(orm以及schema勋眯、model婴梧、entity)下梢,最后給出CRUD操作,希望讀者能夠認(rèn)真體會(huì)orm和具體分層含義志秃。
本節(jié)以最簡(jiǎn)單的user怔球,結(jié)合ava完成單元測(cè)試,我們測(cè)試數(shù)據(jù)庫(kù)代碼并不一定要在koa或其他框架內(nèi)部浮还,最小化問題税迷,mongoose它只是一個(gè)node模塊,這樣對(duì)于我們理解它是比較好的方式爆价。接下來我們會(huì)講解更多高級(jí)mongoose技巧敏簿,它們的基礎(chǔ)都是本節(jié)內(nèi)容,所以本節(jié)必須掌握洼冻,是本章重點(diǎn)崭歧。