mongoDB簡介
mongoDB與一些關系型數據庫相比,它更顯得輕巧、靈活,非常適合在數據規模很大、事務性不強的場合下使用。同時它也是一個對象數據庫,沒有表、行等概念,也沒有固定的模式和結構,所有的數據以文檔的形式存儲。
·由c++語言編寫,是一個分布式文件存儲的開源NoSQL數據庫系統。在高負載的情況下,添加更多的節點,可以保證服務器性能。
· mongoDB旨在為web應用提供可擴展的高性能數據存儲解決方案
· mongoDB將數據存儲為一個文檔,數據結構由鍵值對組成。mongoDB文檔類似於JSON對象,字段值可以包含其他文檔、數組及文檔數組。
安裝 https:www.mongodb.org/download下載安裝包
安裝可視化工具,如robomongo、mongovue等
mongodb的啟動與連接
- windows啟動服務器端 找到mongodb的安裝目錄(比如是D:\mongodb),shift+右鍵打開命令窗口,新建一個data文件夾,在命令行中輸入
mongod --dbpath=D:\mongodb\data
如果出現connections on port 27017就表示啟動成功並在27017端口上監聽了客戶端的請求。--dbpath后的值表示數據庫文件的存儲路徑,而且后面的路徑必須事先創建好,必須已經存在,否則服務開啟失敗。另外,這個命令窗體一旦關閉就相當於停止了mongodb的服務。
- 啟動客戶端連接服務器 找到mongodb的安裝目錄,比如D:\mongodb\bin,在該目錄下打開命令行窗口,輸入mongo --host=127.0.0.1或者mongo,按回車鍵,其中--host后的值表示服務器的ip地址,127.0.0.1表示的是本地服務器,每次數據庫都會默認連接test數據庫
mongodb基本概念
·數據庫
1,一個mongoDB可以建立多個數據庫
2,mongoDB的單個實例可以容納多個獨立的數據庫,每一個都有自己的集合和權限,不同的數據庫也放置在不同的文件中。
3,數據庫也通過名字來標識,數據庫名可以是滿足一下條件的任意utf8字符串
- 不能是空字符串
- 不能含有空格、.、$、/、\和\0(空字符)
- 應全部小寫
- 最多64字節
4, 有一些數據庫名是保留的,可以直接訪問這些有特殊作用的數據庫
- admin:’root‘數據庫,要是將一個用戶添加到這個數據庫,這個用戶自動繼承所有數據庫的權限,一些特定的服務器端命令也只能從這個數據庫運行,比如列出所有的數據庫或者關閉服務器
- local:這個數據庫永遠不會被復制,可以用來存儲於本地單台服務器的任意集合
- config:當mongoDB用於分片設置時,config數據庫在內部使用,用於保存分片的相關信息
·文檔(相當於row)
文檔是mongoDB中的核心單元,可以將文檔類比成關系數據庫中的每一行數據。多個鍵及其關聯的值有序的放置在一起就是文檔。mongoDB使用了BSON這種結構來存儲數據和網絡數據交換。BSON數據可以理解為在JSON的基礎上添加了一些json中沒有的數據類型。
·集合(相當於table)
集合就是一組文檔的組合,如果將文檔類比成數據庫中的行,那么集合就可以類比成數據庫的表。在mongoDB中的集合是無模式的,也就是說集合中存儲的文檔的結構可以是不同的,比如下面的兩個文檔可以同時存入到一個集合中
{"name":"lucy"}{"Name":"lily","sex":"女"} 注:當第一個文檔插入時,集合就會被創建
·字段field(相當於column)
對mongoDB的基礎操作
數據庫的方法 help
·創建數據庫 use database_name 注:如果數據庫不存在,則創建數據庫,否則切換到指定數據庫
·查看所有數據庫 show dbs 注:如果新建一個數據庫沒有顯示,則需要向新建的數據庫插入一些數據db.collection_name.insert({name:'zhangsan'})
·查看當前使用的數據庫 db或db.getName() 注:db代表的是當前數據庫
·刪除數據庫 db.dropDatabase()
·斷開mongodb與mongodb服務的連接 exit
操作集合方法 db.worker.help()查看幫助api
·查看當前數據庫下有哪些集合 show collections
·創建集合 db.createCollection("collection_name")
·向集合中插入文檔 db.collection_name.insert(document) 注:document指要插入的文檔
·查看集合中有多少條document數據 db.collection_name.count()
·刪除當前數據庫中的集合 db.collection_name.drop()
文檔的方法
·插入文檔 db.collection_name.insert(document) 插入文檔后會自動生成一個_id號,_id的類型是ObjectId類型的
也可以用數組的方式一次向集合中插入多條文檔db.collection_name.insert([document1,document2])
·查詢集合中的所有文檔 db.collection_name find()
·使用save方法插入文檔(插入或者更新),_id如果存在就更新,_id如果不存在就插入。用法與insert類似
·更新已經存在的文檔 db.collection_name.update(<query>,<update>,{upsert:<boolean>,multi:<boolean>,writeConcern:<document>})
- query:update的查詢條件,類似sql update查詢的where后面的
- update:update的對象和一些更新的操作符(如$set,$inc...),$inc在原基礎上累加后更新,$set直接更新
- multi:可選,默認false,只更新找到的第一條記錄;如果為true,就把按條件查出來的多條記錄全部更新
eg: db.worker.update({name:'zhangsan'},{$set:{name:'zhangsan123'}})
擴展
存儲在mongodb集合中的每個文檔都有一個默認的主鍵_id,這個主鍵名稱是固定的,它可以是mongodb支持的任何數據類型,默認是ObjectId。該類型的值由系統自己生成,從某種意義上說不會重復。mysql等關系型數據庫的主鍵都是自增的。但在分布式環境下,這種方法不可行,會產生沖突。因此,mongoDB采用ObjectId的類型來做主鍵。Objectid是一個12字節的BSON類型字符串。
Mongoose
mongoose是mongoDB的一個對象模型工具,是基於node-mongodb-native開發的mongoDB的nodejs驅動,可以在異步的環境下執行。同時它也是針對mongoDB操作的一個對象模型庫,封裝了mongoDB對文檔的一些增刪改查等常用方法,讓nodejs操作mongoDB數據庫變得更加容易。
·安裝mongoose
npm install mongoose
·引用mongoose
var mongoose = require('mongoose')
·使用mongoose連接數據庫
var db = mongoose.connect('mongodb://user:pass@localhost:port/database')
·執行下面代碼檢查默認數據庫test,是否可以正常連接成功
//2 加載模塊
var mongoose = require("mongoose"); //3. 連接數據庫 mongod 服務器端 mongo客戶端 //數據庫的名稱可以是不存在 創建一個zf數據庫
var db = mongoose.connect("mongodb://123.57.143.189:27017/zf"); //如果連接成功會執行error回調
db.connection.on("error", function (error) { console.log("數據庫連接失敗:" + error); }); //如果連接成功會執行open回調
db.connection.on("open", function () { console.log("數據庫連接成功"); }); //定義一個 schema,描述此集合里有哪些字段,字段是什么類型 //只有schema中有的屬性才能被保存到數據庫中
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:''} }); //創建模型,可以用它來操作數據庫中的person集合,指的是整體
var PersonModel = db.model("person", PersonSchema); //根據模型創建實體,是指的個體對象
var personEntity = new PersonModel({ name : "zf", age : 6, email: "zf@qq.com", home:'beijing' }); //用save 方法把自己保存到數據庫中
personEntity.save(function(error,doc){ if(error){ console.log("error :" + error); }else{ console.log(doc); } });
如果要通過mongoose創建一個集合並對其進行增刪改查,就需要用到Schema(數據屬性模型)、Model、Entity
Schema簡述
這是一種以文件形式存儲的數據庫模型骨架,無法直接通往數據庫端,也就是說它不具備對數據庫的操作能力,僅僅只是數據庫模型在程序片段中的一種表現,可以說是數據屬性模型(傳統意義的表結構),又或者是集合的模型骨架。基本屬性類型有字符串、日期型、數值型、布爾型、null、數組、內嵌文檔等。
定義一個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構造生成的模型,除了Schema定義的數據庫骨架以外,還具有數據庫操作的行為,類似於管理數據屬性、行為的類。
通過Schema創建Model
//創建模型,可以用它來操作數據庫中的person集合,指的是整體。創建一個person集合
var PersonModel = db.model("person", PersonSchema);
person:數據庫中的集合名稱,當我們對其添加數據時如果person已經存在,則會保存到其目錄下,如果未存在,則會創建person集合,然后再保存數據。有了model,也就有了操作數據的能力。創建一個Model模型,需要指定兩點:1,集合名稱;2,集合的Schema結構對象。滿足這兩點,就可以操作數據庫啦。
Entity簡述
由Model創建的實體,使用save方法保存數據,Model和Entity都有能影響數據庫的操作,但Model比Entity更具操作性。創建Entity成功后,Schema的屬性就變成了Model和Entity的公共屬性了。
使用Model創建Entity
//根據模型創建實體,是指的個體對象
var personEntity = new PersonModel({ name : "zf", age : 6, email: "zf@qq.com", home:'beijing' });
mongoose基礎操作
·查詢
查詢分為多種類型,如條件查詢、過濾查詢等。obj.find(查詢條件,field,callback),field省略或為null,則返回所有屬性;field中把需要顯示的屬性設置為大於零的數則返回該屬性,_id不指定默認返回,設置_id為0則不返回該屬性,其他字段不指定,默認不返回
Model.find({},function(error,docs){ //若沒有向find傳遞參數,默認的是顯示所有文檔
})
查詢就是返回一個集合中文檔的子集,mongoose模型提供了find、findOne和findById方法用於文檔查詢
findOne查詢單條,當查詢到一個符合條件的數據時,就會停止繼續查詢並返回查詢結果。
//創建模型,可以用它來操作數據庫中的person集合,指的是整體
var PersonModel = db.model("person", PersonSchema); //指定返回的字段 1表示 返回 0 不返回 ,, //如果不指定的字段默認不返回 //_id如果不指定也會返回,如果不想讓他返回需要顯式指定為0
PersonModel.find({},{name:1, age:1, _id:0},function(err,docs){ console.log(docs); }) //當找到第一條匹配的記錄時就立刻返回,不再繼續查找了,返回單個對象
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); })
-高級查詢
使用$gt(>)、$lt(<)、$lte(<=)、$gte(>=)、$ne(不等於)、$in(包含)、$or(或者)、$exists(是否存在)操作符進行排除性的查詢
//創建模型,可以用它來操作數據庫中的person集合,指的是整體
var PersonModel = db.model("person", PersonSchema); PersonModel.find({'age':{"$gt":6}},{name:1, age:1, _id:0},function(err,docs){ //查詢age>6的數據
console.log(docs); }) PersonModel.find({'age':{"$gt":6,“$lt”:9}},{name:1, age:1, _id:0},function(err,docs){ //查詢6<age<9的數據
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的數據
console.log(docs); }) PersonModel.find({"name":{"$in":"zf"}},{name:1, age:1, _id:0},function(err,docs){ //查詢name=='zf'的所有數據
console.log(docs); }) PersonModel.find({"age":{"$in":[6,7]}},{name:1, age:1, _id:0},function(err,docs){ //查詢age==6或7的所有數據
console.log(docs); }) PersonModel.find({ age:{ $in: 6}},function(error,docs){ //查詢age等於6的所有數據
console.log(docs); }); PersonModel.find({ age:{$in:[6,10000]}},function(error,docs){ //可以把多個值組織成一個數組
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); });
-游標操作
數據庫使用游標返回find的執行結果,客戶端對游標的實現通常能夠對最終結果進行有效的控制。可以限制結果的數量,略過部分結果,根據任意鍵按任意順序的組合對結果進行各種排序,或者是其他操作。最常用的查詢選項就是限制返回結果的數量(limit函數)、忽略一點數量的結果(skip函數)以及排序(sort函數)。所有這些選項一定要在查詢被發送到服務器之前指定。
-limit函數的基本用法 在查詢操作中,有時數據量會很大,這時我們就需要對返回結果的數量進行限制,就可以使用limit函數來限制結果數量
PersonModel.find({name:/zf/},null,{limit:10},function(err,docs){ console.log(docs); });
-skip函數的基本用法 與limit類似,都是對返回結果數量進行操作,不同的是skip函數的功能是略過指定數量的匹配結果,返回余下的查詢結果
-sort函數的基本用法 將查詢結果進行排序操作,該函數的參數是一個或多個鍵值對,鍵表示要排序的鍵名,值表示排序的方向,1是升序,-1是降序
//現在要分頁查詢,每頁3條,查詢第2頁 //skip 跳過的條數 limit 限制返回的條數 sort排序 1升序 -1 降序 執行的時候會先排序再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方法來對數據進行保存。 Model.create(文檔數據,callback)
//向集合中插入10個文檔
for(var i=1;i<=10;i++){ //向數據中保存文檔
PersonModel.create({name:'zfpx'+i,age:i},function(err,doc){ if(err)console.log(err); else console.log(doc);// doci
}); //所有的異步方法都是在所有的同步方法執行完畢之后才執行的
console.log(i); }
-Entity提供了一個save方法對數據進行保存。Entity.save(文檔數據,callback)
//根據模型創建實體,是指的個體對象
var personEntity = new PersonModel({ name : "zf", age : 6, email: "zf@qq.com", home:'beijing' }); //用save 方法把自己保存到數據庫中
personEntity.save(function(error,doc){ if(error){ console.log("error :" + error); }else{ console.log(doc); } });
·數據更新
Model.update(查詢條件,更新對象,callback) 默認更新一條文檔,若想全部更新,需要加上{multi:true}
//創建模型,可以用它來操作數據庫中的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!'); } });
·數據刪除 Model.remove(查詢條件,callback)
PersonModel.remove({name:'zf'},function(err,docs){ //result: { ok: 1, n: 3 }
console.log(docs); });