mongoDB簡介
mongoDB與一些關(guān)系型數(shù)據(jù)庫相比,它更顯得輕巧鹦聪、靈活,非常適合在數(shù)據(jù)規(guī)模很大泽本、事務(wù)性不強的場合下使用淘太。同時它也是一個對象數(shù)據(jù)庫规丽,沒有表、行等概念赌莺,也沒有固定的模式和結(jié)構(gòu)冰抢,所有的數(shù)據(jù)以文檔的形式存儲艘狭。
·由c++語言編寫挎扰,是一個分布式文件存儲的開源NoSQL數(shù)據(jù)庫系統(tǒng)。在高負(fù)載的情況下遵倦,添加更多的節(jié)點,可以保證服務(wù)器性能骇吭。
· mongoDB旨在為web應(yīng)用提供可擴展的高性能數(shù)據(jù)存儲解決方案
· mongoDB將數(shù)據(jù)存儲為一個文檔,數(shù)據(jù)結(jié)構(gòu)由鍵值對組成燥狰。mongoDB文檔類似于JSON對象棘脐,字段值可以包含其他文檔龙致、數(shù)組及文檔數(shù)組。
安裝 https:www.mongodb.org/download下載安裝包
安裝可視化工具目代,如robomongo屈梁、mongovue等
mongodb的啟動與連接
- windows啟動服務(wù)器端 找到mongodb的安裝目錄(比如是D:\mongodb)榛了,shift+右鍵打開命令窗口在讶,新建一個data文件夾霜大,在命令行中輸入
mongod --dbpath=D:\mongodb\data
如果出現(xiàn)connections on port 27017就表示啟動成功并在27017端口上監(jiān)聽了客戶端的請求。--dbpath后的值表示數(shù)據(jù)庫文件的存儲路徑战坤,而且后面的路徑必須事先創(chuàng)建好曙强,必須已經(jīng)存在途茫,否則服務(wù)開啟失敗碟嘴。另外囊卜,這個命令窗體一旦關(guān)閉就相當(dāng)于停止了mongodb的服務(wù)。
- 啟動客戶端連接服務(wù)器 找到mongodb的安裝目錄栅组,比如D:\mongodb\bin袱衷,在該目錄下打開命令行窗口笑窜,輸入mongo --host=127.0.0.1或者mongo致燥,按回車鍵排截,其中--host后的值表示服務(wù)器的ip地址嫌蚤,127.0.0.1表示的是本地服務(wù)器,每次數(shù)據(jù)庫都會默認(rèn)連接test數(shù)據(jù)庫
mongodb基本概念
·數(shù)據(jù)庫
1脱吱,一個mongoDB可以建立多個數(shù)據(jù)庫
2,mongoDB的單個實例可以容納多個獨立的數(shù)據(jù)庫箱蝠,每一個都有自己的集合和權(quán)限,不同的數(shù)據(jù)庫也放置在不同的文件中宦搬。
3,數(shù)據(jù)庫也通過名字來標(biāo)識间校,數(shù)據(jù)庫名可以是滿足一下條件的任意utf8字符串
- 不能是空字符串
- 不能含有空格矾克、.憔足、$胁附、/滓彰、\和\0(空字符)
- 應(yīng)全部小寫
- 最多64字節(jié)
4控妻, 有一些數(shù)據(jù)庫名是保留的揭绑,可以直接訪問這些有特殊作用的數(shù)據(jù)庫
- admin:’root‘?dāng)?shù)據(jù)庫,要是將一個用戶添加到這個數(shù)據(jù)庫洗做,這個用戶自動繼承所有數(shù)據(jù)庫的權(quán)限弓叛,一些特定的服務(wù)器端命令也只能從這個數(shù)據(jù)庫運行诚纸,比如列出所有的數(shù)據(jù)庫或者關(guān)閉服務(wù)器
- local:這個數(shù)據(jù)庫永遠不會被復(fù)制,可以用來存儲于本地單臺服務(wù)器的任意集合
- config:當(dāng)mongoDB用于分片設(shè)置時畦徘,config數(shù)據(jù)庫在內(nèi)部使用,用于保存分片的相關(guān)信息
·文檔(相當(dāng)于row)
文檔是mongoDB中的核心單元井辆,可以將文檔類比成關(guān)系數(shù)據(jù)庫中的每一行數(shù)據(jù)。多個鍵及其關(guān)聯(lián)的值有序的放置在一起就是文檔溶握。mongoDB使用了BSON這種結(jié)構(gòu)來存儲數(shù)據(jù)和網(wǎng)絡(luò)數(shù)據(jù)交換。BSON數(shù)據(jù)可以理解為在JSON的基礎(chǔ)上添加了一些json中沒有的數(shù)據(jù)類型睡榆。
·集合(相當(dāng)于table)
集合就是一組文檔的組合袍榆,如果將文檔類比成數(shù)據(jù)庫中的行,那么集合就可以類比成數(shù)據(jù)庫的表包雀。在mongoDB中的集合是無模式的,也就是說集合中存儲的文檔的結(jié)構(gòu)可以是不同的亲铡,比如下面的兩個文檔可以同時存入到一個集合中
{"name":"lucy"}{"Name":"lily","sex":"女"} 注:當(dāng)?shù)谝粋€文檔插入時,集合就會被創(chuàng)建
·字段field(相當(dāng)于column)
對mongoDB的基礎(chǔ)操作
數(shù)據(jù)庫的方法 help
·創(chuàng)建數(shù)據(jù)庫 use database_name 注:如果數(shù)據(jù)庫不存在奖蔓,則創(chuàng)建數(shù)據(jù)庫,否則切換到指定數(shù)據(jù)庫
·查看所有數(shù)據(jù)庫 show dbs 注:如果新建一個數(shù)據(jù)庫沒有顯示锭硼,則需要向新建的數(shù)據(jù)庫插入一些數(shù)據(jù)db.collection_name.insert({name:'zhangsan'})
·查看當(dāng)前使用的數(shù)據(jù)庫 db或db.getName() 注:db代表的是當(dāng)前數(shù)據(jù)庫
·刪除數(shù)據(jù)庫 db.dropDatabase()
·斷開mongodb與mongodb服務(wù)的連接 exit
操作集合方法 db.worker.help()查看幫助api
·查看當(dāng)前數(shù)據(jù)庫下有哪些集合 show collections
·創(chuàng)建集合 db.createCollection("collection_name")
·向集合中插入文檔 db.collection_name.insert(document) 注:document指要插入的文檔
·查看集合中有多少條document數(shù)據(jù) db.collection_name.count()
·刪除當(dāng)前數(shù)據(jù)庫中的集合 db.collection_name.drop()
文檔的方法
·插入文檔 db.collection_name.insert(document) 插入文檔后會自動生成一個_id號,_id的類型是ObjectId類型的
也可以用數(shù)組的方式一次向集合中插入多條文檔db.collection_name.insert([document1,document2])
·查詢集合中的所有文檔 db.collection_name find()
·使用save方法插入文檔(插入或者更新),_id如果存在就更新檀头,_id如果不存在就插入。用法與insert類似
·更新已經(jīng)存在的文檔 db.collection_name.update(<query>,<update>,{upsert:<boolean>,multi:<boolean>,writeConcern:<document>})
- query:update的查詢條件暑始,類似sql update查詢的where后面的
- update:update的對象和一些更新的操作符(如inc...),
set直接更新
- multi:可選廊镜,默認(rèn)false,只更新找到的第一條記錄牙肝;如果為true嗤朴,就把按條件查出來的多條記錄全部更新
eg: db.worker.update({name:'zhangsan'},{$set:{name:'zhangsan123'}})
擴展
存儲在mongodb集合中的每個文檔都有一個默認(rèn)的主鍵_id,這個主鍵名稱是固定的雹姊,它可以是mongodb支持的任何數(shù)據(jù)類型股缸,默認(rèn)是ObjectId吱雏。該類型的值由系統(tǒng)自己生成敦姻,從某種意義上說不會重復(fù)歧杏。mysql等關(guān)系型數(shù)據(jù)庫的主鍵都是自增的镰惦。但在分布式環(huán)境下犬绒,這種方法不可行旺入,會產(chǎn)生沖突凯力。因此急膀,mongoDB采用ObjectId的類型來做主鍵。Objectid是一個12字節(jié)的BSON類型字符串龄捡。
Mongoose
mongoose是mongoDB的一個對象模型工具,是基于node-mongodb-native開發(fā)的mongoDB的nodejs驅(qū)動聘殖,可以在異步的環(huán)境下執(zhí)行。同時它也是針對mongoDB操作的一個對象模型庫奸腺,封裝了mongoDB對文檔的一些增刪改查等常用方法,讓nodejs操作mongoDB數(shù)據(jù)庫變得更加容易突照。
·安裝mongoose
npm install mongoose
·引用mongoose
var mongoose = require('mongoose')
·使用mongoose連接數(shù)據(jù)庫
var db = mongoose.connect('mongodb://user:pass@localhost:port/database')
·執(zhí)行下面代碼檢查默認(rèn)數(shù)據(jù)庫test帮非,是否可以正常連接成功
//2 加載模塊
var mongoose = require("mongoose");
//3. 連接數(shù)據(jù)庫 mongod 服務(wù)器端 mongo客戶端
//數(shù)據(jù)庫的名稱可以是不存在 創(chuàng)建一個zf數(shù)據(jù)庫
var db = mongoose.connect("mongodb://123.57.143.189:27017/zf");
//如果連接成功會執(zhí)行error回調(diào)
db.connection.on("error", function (error) {
console.log("數(shù)據(jù)庫連接失敹锬ⅰ:" + error);
});
//如果連接成功會執(zhí)行open回調(diào)
db.connection.on("open", function () {
console.log("數(shù)據(jù)庫連接成功");
});
//定義一個 schema,描述此集合里有哪些字段,字段是什么類型
//只有schema中有的屬性才能被保存到數(shù)據(jù)庫中
var PersonSchema = new mongoose.Schema({
name : { type:String },
home : { type:String },
age : { type:Number, default:0 },
time : { type:Date, default:Date.now },
email: { type:String,default:''}
});
//創(chuàng)建模型座慰,可以用它來操作數(shù)據(jù)庫中的person集合陨舱,指的是整體
var PersonModel = db.model("person", PersonSchema);
//根據(jù)模型創(chuàng)建實體版仔,是指的個體對象
var personEntity = new PersonModel({
name : "zf",
age : 6,
email: "zf@qq.com",
home:'beijing'
});
//用save 方法把自己保存到數(shù)據(jù)庫中
personEntity.save(function(error,doc){
if(error){
console.log("error :" + error);
}else{
console.log(doc);
}
});
如果要通過mongoose創(chuàng)建一個集合并對其進行增刪改查,就需要用到Schema(數(shù)據(jù)屬性模型)蛮粮、Model益缎、Entity
Schema簡述
這是一種以文件形式存儲的數(shù)據(jù)庫模型骨架然想,無法直接通往數(shù)據(jù)庫端莺奔,也就是說它不具備對數(shù)據(jù)庫的操作能力又沾,僅僅只是數(shù)據(jù)庫模型在程序片段中的一種表現(xiàn)弊仪,可以說是數(shù)據(jù)屬性模型(傳統(tǒng)意義的表結(jié)構(gòu))杖刷,又或者是集合的模型骨架』迹基本屬性類型有字符串、日期型表窘、數(shù)值型典予、布爾型乐严、null瘤袖、數(shù)組昂验、內(nèi)嵌文檔等捂敌。
定義一個Schema:
var PersonSchema = new monoose.Schema({
name:{type:String},
age:{type:Number,default:0} ,
time:{type:Date,default:Date.now},
email:{type:String,default:''}
})
Model簡述
由Schema構(gòu)造生成的模型既琴,除了Schema定義的數(shù)據(jù)庫骨架以外占婉,還具有數(shù)據(jù)庫操作的行為甫恩,類似于管理數(shù)據(jù)屬性逆济、行為的類磺箕。
通過Schema創(chuàng)建Model
//創(chuàng)建模型奖慌,可以用它來操作數(shù)據(jù)庫中的person集合松靡,指的是整體升薯。創(chuàng)建一個person集合
var PersonModel = db.model("person", PersonSchema);
person:數(shù)據(jù)庫中的集合名稱击困,當(dāng)我們對其添加數(shù)據(jù)時如果person已經(jīng)存在涎劈,則會保存到其目錄下阅茶,如果未存在蛛枚,則會創(chuàng)建person集合脸哀,然后再保存數(shù)據(jù)蹦浦。有了model撞蜂,也就有了操作數(shù)據(jù)的能力盲镶。創(chuàng)建一個Model模型蝌诡,需要指定兩點:1溉贿,集合名稱浦旱;2宇色,集合的Schema結(jié)構(gòu)對象。滿足這兩點宣蠕,就可以操作數(shù)據(jù)庫啦。
Entity簡述
由Model創(chuàng)建的實體抢蚀,使用save方法保存數(shù)據(jù),Model和Entity都有能影響數(shù)據(jù)庫的操作皿曲,但Model比Entity更具操作性鹿响。創(chuàng)建Entity成功后谷饿,Schema的屬性就變成了Model和Entity的公共屬性了喘沿。
使用Model創(chuàng)建Entity
//根據(jù)模型創(chuàng)建實體,是指的個體對象
var personEntity = new PersonModel({
name : "zf",
age : 6,
email: "zf@qq.com",
home:'beijing'
});
mongoose基礎(chǔ)操作
·查詢
查詢分為多種類型,如條件查詢咏窿、過濾查詢等率寡。obj.find(查詢條件职烧,field虑绵,callback),field省略或為null,則返回所有屬性翅睛;field中把需要顯示的屬性設(shè)置為大于零的數(shù)則返回該屬性声搁,_id不指定默認(rèn)返回捕发,設(shè)置_id為0則不返回該屬性,其他字段不指定疏旨,默認(rèn)不返回
Model.find({},function(error,docs){
//若沒有向find傳遞參數(shù)扎酷,默認(rèn)的是顯示所有文檔
})
查詢就是返回一個集合中文檔的子集檐涝,mongoose模型提供了find法挨、findOne和findById方法用于文檔查詢
findOne查詢單條谁榜,當(dāng)查詢到一個符合條件的數(shù)據(jù)時凡纳,就會停止繼續(xù)查詢并返回查詢結(jié)果。
//創(chuàng)建模型惫企,可以用它來操作數(shù)據(jù)庫中的person集合撕瞧,指的是整體
var PersonModel = db.model("person", PersonSchema);
//指定返回的字段 1表示 返回 0 不返回 狞尔,,
//如果不指定的字段默認(rèn)不返回
//_id如果不指定也會返回丛版,如果不想讓他返回需要顯式指定為0
PersonModel.find({},{name:1, age:1, _id:0},function(err,docs){
console.log(docs);
})
//當(dāng)找到第一條匹配的記錄時就立刻返回偏序,不再繼續(xù)查找了页畦,返回單個對象
PersonModel.findOne({name:/^\w+9$/},{name:1, age:1, _id:0},function(err,doc){
console.log(doc);
})
//按照ID進行查詢
PersonModel.findById('56ee117356acb568054dd6d4',{name:1, age:1, _id:0},function(err,doc){
console.log(doc);
})
-高級查詢
使用lt(<)、
gte(>=)好芭、
in(包含)舍败、
exists(是否存在)操作符進行排除性的查詢
//創(chuàng)建模型邻薯,可以用它來操作數(shù)據(jù)庫中的person集合乘凸,指的是整體
var PersonModel = db.model("person", PersonSchema);
PersonModel.find({'age':{"$gt":6}},{name:1, age:1, _id:0},function(err,docs){
//查詢age>6的數(shù)據(jù)
console.log(docs);
})
PersonModel.find({'age':{"$gt":6,“$lt”:9}},{name:1, age:1, _id:0},function(err,docs){
//查詢6<age<9的數(shù)據(jù)
console.log(docs);
})
PersonModel.find({"name":{"$ne":"zf"},'age':{"$gt":6营勤,“$lt”:9}},{name:1, age:1, _id:0},function(err,docs){
//查詢name!='zf'&&6<age<9的數(shù)據(jù)
console.log(docs);
})
PersonModel.find({"name":{"$in":"zf"}},{name:1, age:1, _id:0},function(err,docs){
//查詢name=='zf'的所有數(shù)據(jù)
console.log(docs);
})
PersonModel.find({"age":{"$in":[6,7]}},{name:1, age:1, _id:0},function(err,docs){
//查詢age==6或7的所有數(shù)據(jù)
console.log(docs);
})
PersonModel.find({ age:{ $in: 6}},function(error,docs){
//查詢age等于6的所有數(shù)據(jù)
console.log(docs);
});
PersonModel.find({ age:{$in:[6,10000]}},function(error,docs){
//可以把多個值組織成一個數(shù)組
console.log(docs);
});
PersonModel.find({email:'email',"$or":[{"name":"zfpx1"},{"age":2000}]},function(error,docs){
//查詢name為zfpx或age為6的全部文檔
console.log(docs);
});
var start = new Date();
var end = new Date();
PersonModel.find({time:{$lt:end},time:{$gt:start}},function(error,docs){
//查詢name為zfpx或age為6的全部文檔
console.log(docs);
});
-游標(biāo)操作
數(shù)據(jù)庫使用游標(biāo)返回find的執(zhí)行結(jié)果,客戶端對游標(biāo)的實現(xiàn)通常能夠?qū)ψ罱K結(jié)果進行有效的控制葛作⌒训冢可以限制結(jié)果的數(shù)量进鸠,略過部分結(jié)果稠曼,根據(jù)任意鍵按任意順序的組合對結(jié)果進行各種排序客年,或者是其他操作霞幅。最常用的查詢選項就是限制返回結(jié)果的數(shù)量(limit函數(shù))量瓜、忽略一點數(shù)量的結(jié)果(skip函數(shù))以及排序(sort函數(shù))司恳。所有這些選項一定要在查詢被發(fā)送到服務(wù)器之前指定绍傲。
-limit函數(shù)的基本用法 在查詢操作中扔傅,有時數(shù)據(jù)量會很大,這時我們就需要對返回結(jié)果的數(shù)量進行限制猎塞,就可以使用limit函數(shù)來限制結(jié)果數(shù)量
PersonModel.find({name:/zf/},null,{limit:10},function(err,docs){
console.log(docs);
});
-skip函數(shù)的基本用法 與limit類似,都是對返回結(jié)果數(shù)量進行操作荠耽,不同的是skip函數(shù)的功能是略過指定數(shù)量的匹配結(jié)果,返回余下的查詢結(jié)果
-sort函數(shù)的基本用法 將查詢結(jié)果進行排序操作铝量,該函數(shù)的參數(shù)是一個或多個鍵值對倘屹,鍵表示要排序的鍵名慢叨,值表示排序的方向纽匙,1是升序拍谐,-1是降序
//現(xiàn)在要分頁查詢哄辣,每頁3條赠尾,查詢第2頁
//skip 跳過的條數(shù) limit 限制返回的條數(shù) sort排序 1升序 -1 降序 執(zhí)行的時候會先排序再skip力穗,再limit
PersonModel.find({},{_id:0,name:1},{limit:3,skip:3,sort:{age:1,name:-1}},function(err,docs){
console.log(docs);
});
·保存
-Model提供了一個create方法來對數(shù)據(jù)進行保存气嫁。 Model.create(文檔數(shù)據(jù)当窗,callback)
//向集合中插入10個文檔
for(var i=1;i<=10;i++){
//向數(shù)據(jù)中保存文檔
PersonModel.create({name:'zfpx'+i,age:i},function(err,doc){
if(err)console.log(err);
else
console.log(doc);// doci
});
//所有的異步方法都是在所有的同步方法執(zhí)行完畢之后才執(zhí)行的
console.log(i);
}
-Entity提供了一個save方法對數(shù)據(jù)進行保存寸宵。Entity.save(文檔數(shù)據(jù),callback)
//根據(jù)模型創(chuàng)建實體梯影,是指的個體對象
var personEntity = new PersonModel({
name : "zf",
age : 6,
email: "zf@qq.com",
home:'beijing'
});
//用save 方法把自己保存到數(shù)據(jù)庫中
personEntity.save(function(error,doc){
if(error){
console.log("error :" + error);
}else{
console.log(doc);
}
});
·數(shù)據(jù)更新
Model.update(查詢條件,更新對象,callback) 默認(rèn)更新一條文檔巫员,若想全部更新甲棍,需要加上{multi:true}
//創(chuàng)建模型简识,可以用它來操作數(shù)據(jù)庫中的person集合感猛,指的是整體
var PersonModel = db.model("person", PersonSchema);
//$set更新器 指定要更新的字段
var update = {$set : { age : 100 }};
//更新
//multi 更新匹配到的所有的記錄
PersonModel.update({name : 'zf'}, update,{multi:true}, function(error){
if(error) {
console.log(error);
} else {
console.log('Update success!');
}
});
·數(shù)據(jù)刪除 Model.remove(查詢條件,callback)
PersonModel.remove({name:'zf'},function(err,docs){
//result: { ok: 1, n: 3 }
console.log(docs);
});