將js進行到底:node學習8
Node.js與數據庫之MongoDB
廢話:現代web開發可以說完全是數據庫驅動的,而對於我這樣的PHP程序員來說,對Mysql向來十分鐘情,MongoDB的興起讓我不能再對Mysql孤註一擲,《了不起的node.js》一書中首推的數據庫就是MongoDB,也許其性能和功能並沒有Mysql那麽強大,靠山也沒有oracle這樣的大公司,但是為什麽我覺得值得去研究和使用,在這之前,我們先來說說MongoDB好處都有啥!
MongoDB
首先,MongoDB非常的年輕,生於2012年,然後他是一個基於分布式文件存儲的數據庫。他非常適合Node.js應用。
MongoDB的定位介於關系型數據庫和非關系型數據庫,支持的數據結構松散,類似於json。
和Mysql最大的區別是:mysql需要按照固定的表結構存儲數據,而mongo可以將任意類型的文檔數據存儲在集合中。
當MongoDB與Node.js強強聯手時,基本存儲格式都是json,因此數據庫——後端——前端的數據格式可以得到較好統一,這是最騷的!我覺得json真的是我最愛的web數據傳輸格式。
最後,MongoDB雖然不是完整的關系型數據庫,但依然強於NoSQL類型數據庫,因為他並非簡單的鍵值對存儲,而是可以多層次(就是類似json),對象下還可以存儲對象,這就使得他可以存儲較為復雜的數據結構和關系,所以這真的就牛逼了。
至於性能,自行研究,參考:https://www.cnblogs.com/web-fusheng/p/6884759.html
Windows下安裝MongoDB
別說安裝一步到位,我在windows下安裝還真遇到一些小坑。
首先官方下載地址:https://www.mongodb.com/download-center#community
我下載的是社區版本,一般個人就使用社區版就行了,之前oracle學習我也使用社區版的。
安裝選擇custom模式,安裝目錄下有個bin目錄,將其添加到環境變量中
打開cmd,安裝mongoDB服務,註意這一點很關鍵,直接啟動Mongo是不行的,另外盡量用管理員身份運行cmd去做以下操作
mongod --dbpath D:\Programs\MongoDB\Server\3.6\db --logpath D:\Programs\MongoDB\Server\3.6\log\mongodb.log --install --serviceName "mongo"
這段命令做了兩件事,一件事是設置了數據文件目錄和日誌文件(oracle會在安裝時選擇好),另一件就是把Mongo的服務加入到windows的net服務中去。
接下來:
net start mongo
看到服務啟動成功即可,如果不成功,切換為管理員權限。
連接MongoDB:
mongo
Node.js連接MongoDB
任何一門語言需要連接到數據庫,就需要數據庫的API,以此提供驅動庫,使用前導入驅動庫即可調用API,數據庫驅動的作用就是使得語言理解數據庫連接協議,負責解碼編碼與數據庫交換的數據,保證連接的穩定性等。
在Node.js中使用mongo需要mongodb模塊支持
package.json
{
"name":"user-login-example",
"description":"a user login,register example by using mongoDB",
"version":"0.0.1",
"dependencies":{
"express":"latest",
"mongodb":"latest",
"jade":"latest",
"express-session":"latest"
}
}
連接插入測試:
var mongo = require("mongodb").MongoClient;
//連接到mongo服務
mongo.connect(‘mongodb://localhost:27017‘,function(err,client){
if(err) throw err;
console.log("Connected mongo");
//選擇test庫
db = client.db("test");
//從test中選擇documents這個集合
var collection = db.collection(‘documents‘);
var data = [{a:1},{a:2},{a:3}];
//插入多條數據
collection.insertMany(data,function(err,res){
if(err) throw err;
else console.log("3 documents inserted");
client.close();
});
});
node server
運行之後使用mongo compass查看數據庫裏多的數據
可以看到三條數據已經插入其中
註意:在使用MongoDB API連接後,不存在的數據庫會在操作前創建,不存在集合(collection)會在操作前創建,mango不必擔心數據庫是否存在的問題。collection類似於mysql下的一張表。
這個API可以使用insertMany一次插入多條數據,讓我覺得十分驚奇!
實戰——開發登陸註冊樣例
下面進入簡單的實踐環節,使用node.js和mongoDB開發用戶註冊登陸界面,具體需求:
- 用戶進入登陸界面登陸
- 用戶註冊用戶
- 用戶登陸成功進入個人主頁
需要用jade模塊構建視圖模型,express的session中間件,mongo數據庫存儲用戶註冊信息。
除此以外,是時候介紹以下模塊化思想了:
在web開發中,不可能把所有請求和控制器處理都放在同一個js文件中,應該要為每一個view提供一個controller,這是MVC模式的一種思想,也就是不同頁面處理應當有單獨的文件管理,便於後期維護,減少server.js文件代碼量,不管怎麽說專門的分類看著都讓人爽吶。
需要利用當初學習node第一章時的exports對象,將模塊API暴露給其他模塊使用,實現模塊劃分。
項目文件
views目錄
項目文件構建基本思想是將視圖和控制器分離,控制器模塊化,每一個模塊對應一個視圖文件Jade,構建思想來源於我之前PHP MVC開發經驗。
server.js
var app = require("express")();
var bodyParser = require(‘body-parser‘);
var cookieParser = require(‘cookie-parser‘);
var session = require("express-session");
//引入控制器
var index = require("./index"),
login = require("./login"),
register = require("./register");
app.use(bodyParser.json()); // for parsing application/json
app.use(cookieParser("devilyouwei"));
app.use(bodyParser.urlencoded({ extended: true })); //對post請求表單提交的數據編碼,否則服務器端無法獲得
//使用session中間件
app.use(session({
secret: ‘devilyouwei‘,
resave: false,
saveUninitialized: true,
cookie: { secure: false ,maxAge:3600000}
}));
app.set("view engine","jade");
app.set("views",__dirname+"/views");
app.get("/",index);
app.get("/login",login);
app.get("/register",register);
app.get("/logout",index.logout);
//表單提交請求
app.post("/login",login);
app.post("/register",register);
app.listen(3000);
這是主模塊,提供http服務,並將請求分配到不同的js控制器上
index.js
module.exports=index;
function index(req,res,next){
console.log(req.session);
if(req.session.user)
res.render("index",{authenticated:true,username:req.session.user});
else
res.render("index");
}
index.logout = function(req,res,next){
req.session.user = null;
res.redirect("/");
}
主頁控制,需檢查session
login.js
module.exports = login;
var mongo = require("mongodb").MongoClient;
function login(req,res,next){
if(req.method == "GET")
res.render("login");
else if(req.method == "POST"){
auth(req.body,function(flag){
//通過驗證,賬號密碼正確
if(flag){
req.session.user = flag.email;
req.session.cookie.expires = new Date(Date.now() + 3600000);
req.session.cookie.maxAge = 3600000;
console.log(req.session);
res.redirect("/");
}else{
//賬號密碼錯誤
res.send("賬號密碼錯誤!")
}
});
}else{
res.send(404);
}
}
function auth(data,fn){
mongo.connect(‘mongodb://localhost:27017‘,function(err,client){
if(err) throw err;
db = client.db("test");
var collection = db.collection(‘users‘);
collection.find(data).toArray(function(err,docs){
if(err) throw err;
client.close();
//如果沒找到,數組長度為0,返回false,表示賬號密碼有錯誤
if(docs.length==0) fn(false);
else fn(docs[0]);
});
})
}
登陸模塊,auth方法查詢mangodb匹配賬號密碼
register.js
module.exports = register
var mongo = require("mongodb").MongoClient;
function register(req,res,next){
if(req.method == "GET")
res.render("register");
else if(req.method == "POST"){
//此處需要做安全驗證,略
save(req.body,function(){
res.redirect("/login");
});
}else{
res.send(404);
}
}
//保存用戶註冊信息
function save(data,fn){
mongo.connect(‘mongodb://localhost:27017‘,function(err,client){
if(err) throw err;
console.log("Connected mongo");
db = client.db("test");
var collection = db.collection(‘users‘);
collection.insertMany([data],function(err,res){
if(err) throw err;
else console.log("1 user inserted");
client.close();
fn();
});
})
}
註冊模塊,save方法對mongodb進行寫入操作
代碼不全部列出,jade文件代碼不是重點,故不一一列出,樣例完整代碼下載地址:
http://download.csdn.net/download/u014466109/10251935
將js進行到底:node學習8