mongoose mysql_mongoose入门
mongoose入門
MongoDB是一個開源的NoSQL數據庫,相比MySQL那樣的關系型數據庫,它更顯得輕巧、靈活,非常適合在數據規模很大、事務性不強的場合下使用。同時它也是一個對象數據庫,沒有表、行等概念,也沒有固定的模式和結構,所有的數據以文檔的形式存儲(文檔,就是一個關聯數組式的對象,它的內部由屬性組成,一個屬性對應的值可能是一個數、字符串、日期、數組,甚至是一個嵌套的文檔。),數據格式就是JSON。
假定讀者已經了解了mongdb和mysql的區別和為什么選用mongodb,繼而介紹nodejs里的mongoose模塊進行實戰,具體分4步驟
mongoose是什么?
mongoose入門
mongoose概念
mongoose crud
Mongoose是什么?
Mongoose是MongoDB的一個對象模型工具,是基于node-mongodb-native開發的MongoDB nodejs驅動,可以在異步的環境下執行。同時它也是針對MongoDB操作的一個對象模型庫,封裝了MongoDB對文檔的的一些增刪改查等常用方法,讓NodeJS操作Mongodb數據庫變得更加靈活簡單。
Mongoose,因為封裝了對MongoDB對文檔操作的常用處理方法,可以高效的操作mongodb,同時可以理解mongoose是一個簡易版的orm ,提供了類似schema定義,hook、plugin、virtual、populate等機制,讓NodeJS操作Mongodb數據庫變得特別簡單!
以往書中往往直接上例子,混合各種庫和代碼,容易讓人暈,必須在例子中才能知道m是如何使用的,我一直認為這是不合理的,為什么我要掌握其他的知識才能學mongoose?
其實,它也僅僅是一個node模塊而已。
mongoose入門
前面我們已經認識了Mongoose,也了解了MongoDB,回顧一下:MongoDB是一個對象數據庫,是用來存儲數據的;Mongoose是封裝了MongoDB操作的一個對象模型庫,是用來操作這些數據的。
好,下面我們就來進行操作數據的第一步吧。
準備
1、 安裝mongoose
$ npm install --save mongoose
2、 引用mongoose
var mongoose = require("mongoose");
3、 使用"mongoose"連接數據庫
var db = mongoose.connect("mongodb://user:pass@ip:port/database");
說明
user 是mongodb里用戶名
pass 是mongodb里用戶對應的密碼
ip 是mongodb服務器可以訪問ip地址,比如本地為127.0.0.1
port 是mongodb服務器可以訪問端口,默認是27017
測試
執行下面代碼檢查默認數據庫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("數據庫連接失敗:" + error);
});
db.connection.on("open", function () {
console.log("數據庫連接成功");
});
執行代碼
$ node book-source/db/helloworld/connect.js
數據庫連接成功
當mongodb沒有啟動的時候會報錯,當出現如下問題,請執行mhg啟動mongodb即可
$ node book-source/db/helloworld/connect.js
數據庫連接失敗:MongoError: connect ECONNREFUSED 127.0.0.1:27017
最小demo
這里給出極簡demo,用于講解mongoose從連接數據庫到對數據庫進行操作完整過程,這樣更容易讓讀者了解核心原理,代碼如下:
// 1、引入`mongoose`模塊
var mongoose = require('mongoose');
// 2、通過`mongoose.connect`連接mongodb數據庫
mongoose.connect('mongodb://127.0.0.1/db_helloworld');
// 3、通過`mongoose.model`定義模型(model)
var Cat = mongoose.model('Cat', { name: String });
// 4、通過`new`關鍵字實例化Cat模型,參數是`{ name: 'Zildjian' }`,創建kitty對象
var kitty = new Cat({ name: 'Zildjian' });
// 5、執行`kitty.save`來保存到數據庫
kitty.save(function (err) {
if (err) {
console.log('save error:' + err);
}
console.log('save sucess');
});
核心步驟說明
定義模型(model)
通過new關鍵字實例化Cat模型,創建kitty對象
執行kitty.save來保存到數據庫
這個其實就是mongoose最常見的用法,首先約定schema,即在模型model定義的時候指定字段和字段類型,避免亂用schema-free問題。之后對實例化模型創建的對象進行操作,完成我們常見的增刪改查功能。
模型(model)定義即定義對象,對象操作即對數據庫進行操作
執行如下
$ node book-source/db/helloworld/helloworld.js
如無錯誤日志,即代表數據保存成功。此時打開robo mongodb客戶端查看一下具體數據是否保存成功。
創建robo客戶端連接
[圖片上傳失敗...(image-a2a818-1519355504563)]
查看cat數據
[圖片上傳失敗...(image-a49fdc-1519355504563)]
如果有{ name: 'Zildjian' }記錄的,即為正常。
實例
連接數據庫信息放到獨立文件里
模型定義放到獨立文件
在具體調用的文件里,使用模型定義
連接數據庫
看一下實際代碼,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("數據庫連接失敗:" + error);
});
db.connection.on("open", function () {
console.log("數據庫連接成功");
});
一般項目里,所有模型都共用一個數據庫連接信息,所以把連接數據庫的代碼抽取到connect.js里,然后在對應的模型里會app入口引用即可。
模型定義
看一下實際模型定義代碼,db/mini/user.js
var mongoose = require('mongoose');
// 定義Schema
UserSchema = new mongoose.Schema({
username: {// 真實姓名
type: String,
required: true
},
password: { // 密碼
type: String,
required: true
}
});
// 定義Model
var UserModel = mongoose.model('User', UserSchema);
// 暴露接口
module.exports = UserModel;
這是MVC里Model層最長見的代碼,沒有連接信息,也沒有其他額外不相干代碼,當你看到user.js你就能理解它在數據庫里對應的表結構,以及字段的類型、約束等信息,一般來說,代碼寫的越干凈,可讀性會更好一些。
這里定義的User模型里只有 用戶名 和 密碼 2個字段,它們都必須有值的,也就是說當你創建用戶的時候,沒有密碼或者沒有用戶名你是無法創建成功的。
測試代碼
看一下實際代碼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、對數據庫進行操作
user.save(function(err, doc){
if (err) {
console.log('save error:' + err);
}
console.log('save sucess \n' + doc);
})
核心步驟
引入數據庫連接,保證mongodb已經連接成功
引入模型(model)定義文件,即文檔(表)結構定義
實例化UserModel,創建user實體
最后通過user實體對數據庫進行操作,完成用戶注冊功能。
這是項目里數據訪問層的代碼,它真實的對數據庫進行操作,所以它一般會出現在controller或service層。
執行測試
$ node db/mini/test.js
數據庫連接成功
save sucess
{ _id: 57341fc54d97ee0249082a1d,
password: '0123456789',
username: 'i5ting',
__v: 0 }
概念
結合上面的實例來講4個核心概念,以便于理解
ORM 對象關系映射
Schema
Model 模型
Entity 實體
對象關系映射
對象關系映射(英語:Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序設計技術,用于實現面向對象編程語言里不同類型系統的數據之間的轉換。從效果上說,它其實是創建了一個可在編程語言里使用的“虛擬對象數據庫”。如今已有很多免費和收費的ORM產品,而有些程序員更傾向于創建自己的ORM工具。
面向對象是從軟件工程基本原則(如耦合、聚合、封裝)的基礎上發展起來的,而關系數據庫則是從數學理論發展而來的,兩套理論存在顯著的區別。為了解決這個不匹配的現象,對象關系映射技術應運而生。
對象關系映射(Object-Relational Mapping)提供了概念性的、易于理解的模型化數據的方法。
ORM方法論基于三個核心原則:
簡單:以最基本的形式建模數據。
傳達性:數據庫結構被任何人都能理解的語言文檔化。
精確性:基于數據模型創建正確標準化的結構。
典型地,建模者通過收集來自那些熟悉應用程序但不熟練的數據建模者的人的信息開發信息模型。建模者必須能夠用非技術企業專家可以理解的術語在概念層次上與數據結構進行通訊。建模者也必須能以簡單的單元分析信息,對樣本數據進行處理。ORM專門被設計為改進這種聯系。
讓我們從O/R開始。字母O起源于 對象(OBJECT),而R則來自于 關系(RELATIONAL)。幾乎所有的程序里面,都存在對象和關系數據庫。在業務邏輯層和用戶界面層中,我們是面向對象的。當對象信息發生變化的時候,我們需要把對象的信息保存在關系數據庫中。
最簡單的理解:
ORM是讓用語言中的對象來操作數據庫,至于如何實現就是orm工具實現的,可以理解mongoose是orm工具。
mongoose包括以下四部分:
一個對持久類對象進行CRUD操作的API,可以理解為實體Entity上的方法
一個語言或API用來規定與類和類屬性相關的查詢,比如Population
一個規定MAPPING METADATA的工具,可以理解為Schema定義
一種技術可以讓ORM的實現各種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是一種以文件形式存儲的數據庫模型骨架,無法直接通往數據庫端,也就是說它不具備對數據庫的操作能力,僅僅只是定義數據庫模型在程序片段中的一種表現,可以說是數據屬性模型(傳統意義的表結構),又或著是“集合”的模型骨架。
最簡單的理解:
Schema是對文檔(表)結構的定義
那如何去定義一個Schema呢,請看示例:
// 定義Schema
UserSchema = new mongoose.Schema({
username: {// 真實姓名
type: String,
required: true
},
password: { // 密碼
type: String,
required: true
}
});
基本屬性類型有:字符串、日期型、數值型、布爾型(Boolean)、null、數組、內嵌文檔等,當然它還有更豐富的對字段進行校驗約束的功能。
模型(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構造生成的模型,除了Schema定義的數據庫骨架以外,還具有數據庫操作的行為,類似于管理數據庫屬性、行為的類。
如何通過Schema來創建Model呢,如下示例:
var db = mongoose.connect("mongodb://127.0.0.1:27017/test");
// 創建Model
var TestModel = db.model("test1", TestSchema);
// 定義Model
var UserModel = mongoose.model('User', UserSchema);
User是模型名稱,它對應到mongodb里就是數據庫中的集合名稱,默認會轉成復數,變為'users',當我們對其添加數據時如果users已經存在,則會保存到其目錄下,如果未存在,則會創建users集合,然后在保存數據。
擁有了Model,我們也就擁有了操作數據庫的金鑰匙,在后面的內容中,我們就會學習使用Model來進行增刪改查的具體操作,所以,一定要熟悉他的創建格式喲!
如果你想對某個集合有所作為,那就交給Model模型來處理吧,創建一個Model模型,我們需要指定:1.集合名稱,2.集合的Schema結構對象,滿足這兩個條件,我們就會擁有一個操作數據庫的金鑰匙。
實體(Entity)
Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.
實體(Entity)是由Model創建的實體,使用save方法保存數據,Model和Entity都有能影響數據庫的操作,但Model比Entity更具操作性。
使用Model創建Entity,如下示例:
var user = new User({
username: 'i5ting',
password: '0123456789'
});
console.log(user.username); // i5ting
console.log(user.password); //0123456789
創建成功之后,Schema屬性就變成了Model和Entity的公共屬性了。
總結
Schema是骨架,模型(model)是根據Schema創建的模板,也就是說Schema和Model是定義部分,而實體Entity是模型實例化后創建的對象,它才是真正對數據庫進行操作的。
所以我們會把定義部分(Schema + model)和實體操作部分(Entity)分開,定義是不變的,而實體是對數據庫進行操作,操作類是術語可變的,所以在mvc分層的時候model實際放的是定義部分,而在controller里使用的是實體操作部分的。
基于前面的內容,接下來我們就開始學習對數據的具體操作了,下面是關于一些基礎數據的定義,相信對于你來說已經不陌生了,請在仔細溫習一遍吧!
CRUD(增刪改查)
CRUD為數據庫的最常見的4種基本操作,即增加(Create)、讀取(Retrieve)(重新得到數據)、更新(Update)和刪除(Delete)幾個單詞的首字母簡寫。主要被用在描述軟件系統中數據庫或者持久層的基本操作功能。
mongoose提供如下的crud方法
save
find | findOne
update
remove
下面我們使用user模型為例,給出具體例子
增加(Create)
文檔
Model#save(product,)
@description Saves this document.
Parameters:
- product, Number)} [fn] optional callback
Returns:
Promise
具體代碼
const user = new User({
username: 'i5ting',
password: '0123456789'
});
user.save((err, u) => {
t.false(err);
t.is(u.username, 'i5ting');
});
讀取(Retrieve)
find:根據條件查詢,返回的是數組
文檔
Model.find(conditions, [fields], [options], [callback])
Finds documents
Parameters:
- conditions
- [fields] optional fields to select
- [options] optional
- [callback]
Returns:
代碼
User.find({}, (err, docs) => {
t.false(err);
t.is(docs.length, 1);
t.is(docs[0].username, 'i5ting');
});
findOne:根據條件查詢,返回的是一條數據對象
文檔
Model.findOne([conditions], [fields], [options], [callback])
Finds one document.
Parameters:
- [conditions]
- [fields] optional fields to select
- [options] optional
- [callback]
Returns:
代碼
User.findOne({username: 'i5ting'}, (err, doc) => {
t.false(err);
t.is(doc.length, 1);
t.is(doc.username, 'i5ting');
});
更新(Update)
findByIdAndUpdate:根據ID查找并更新
文檔說明如下
Model.findByIdAndUpdate(id, [update], [options], [callback])
Issues a mongodb findAndModify update command by a documents id.
show code
Parameters:
- id an ObjectId or string that can be cast to one.
- [update]
- [options]
- [callback]
Returns:
具體代碼
User.findByIdAndUpdate(u._id, {
username: 'sang',
}, (err, user) => {
t.false(err);
t.is(user.username, 'sang');
});
findOneAndUpdate:根據查詢條件查找并更新
Model.findOneAndUpdate([conditions], [update], [options], [callback])
Issues a mongodb findAndModify update command.
Parameters:
- [conditions]
- [update]
- [options]
- [callback]
Returns:
具體代碼
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
- [callback]
Returns:
Promise
代碼
User.remove({username: 'i5ting for delete'}, (err, doc) => {
t.false(err);
t.is(doc.result.ok, 1);
t.is(doc.result.n, 1);
});
執行測試
$ cd db
$ npm test
> koa-db@1.0.0 test /Users/sang/workspace/17koa/book-source/db
> ava crud -v
數據庫連接成功
? #save()
? #find() return array
? #findById() return array
? #findOne() return user obj
? #remove()
? #findByIdAndUpdate()
? #findOneAndUpdate()
6 tests passed
調試模式
調試模式是mongoose提供的一個非常實用的功能,用于查看mongoose模塊對mongodb操作的日志,一般開發時會打開此功能,以便更好的了解和優化對mongodb的操作。
打開調試的核心代碼是設置 debug 變量值為 true 即可
var mongoose = require("mongoose");
// 核心代碼,是否開啟測試
mongoose.set('debug', true);
var db = mongoose.connect("mongodb://127.0.0.1:27017/db_helloworld");
db.connection.on("error", function (error) {
console.log("數據庫連接失敗:" + error);
});
db.connection.on("open", function () {
console.log("數據庫連接成功");
});
執行測試如下
$ cd db
$ npm test
> koa-db@1.0.0 test /Users/sang/workspace/17koa/book-source/db
> ava crud -v
數據庫連接成功
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
總結
從mongoose是什么,到如何使用,以及核心概念(orm以及schema、model、entity),最后給出CRUD操作,希望讀者能夠認真體會orm和具體分層含義。
本節以最簡單的user,結合ava完成單元測試,我們測試數據庫代碼并不一定要在koa或其他框架內部,最小化問題,mongoose它只是一個node模塊,這樣對于我們理解它是比較好的方式。接下來我們會講解更多高級mongoose技巧,它們的基礎都是本節內容,所以本節必須掌握,是本章重點。
其他
總結
以上是生活随笔為你收集整理的mongoose mysql_mongoose入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 初中英语多词性单词怎么办_高考英语阅读理
- 下一篇: 在matlab中ungetfile后,1