1.基本操作
1.1服務端
- 服務的指令為mongod,可以通過help檢視所有參數
mongod --help
- 啟動MongoDB服務
net start MongoDB
- 關閉MongoDB服務
net stop MongoDB
1.2用戶端(一個js的編譯器)
如果你需要進入MongoDB背景管理,你需要先打開mongodb裝目錄的下的bin目錄,然後執行mongo.exe檔案,MongoDB Shell是MongoDB自帶的互動式Javascript shell,用來對MongoDB進行操作和管理的互動式環境。
- 當你進入mongoDB背景後,它預設會連結到 test 文檔(資料庫):
> mongo
MongoDB shell version: 3.0.6
connecting to: test
……
- 終端退出連接配接
exit或ctrl+c
1.3資料庫指令
- 連接配接成功後,預設使用test資料庫
- 檢視目前資料庫名稱
db
- 檢視所有資料庫名稱,列出所有在實體上存在的資料庫
show dbs
- 切換資料庫,如果資料庫不存在也并不建立,直到插入資料或建立集合時資料庫才被建立
use 資料庫名稱
- 删除目前指向的資料庫,如果資料庫不存在,則什麼也不做
db.dropDatabase()
1.4集合指令
- 建立文法如下
- name是要建立的集合的名稱
- options是一個文檔,用于指定集合的配置,選項參數是可選的,是以隻需要到指定的集合名稱
- 可以不手動建立集合,向不存在的集合中第一次加入資料時,集合會被建立出來
db.createCollection(name, options)
- 例1:不限制集合大小
db.createCollection("stu")
- 例2:限制集合大小,後面學會插入語句後可以檢視效果
- 參數capped:預設值為false表示不設定上限,值為true表示設定上限
- 參數size:當capped值為true時,需要指定此參數,表示上限大小,當文檔達到上限時,會将之前的資料覆寫,機關為位元組
db.createCollection("sub", { capped : true, size : 10 } )
- 檢視目前資料庫的集合
show collections
- 删除指令
db.集合名稱.drop()
1.5資料類型
- 下表為MongoDB中常用的幾種資料類型:
- Object ID:文檔ID
- String:字元串,最常用,必須是有效的UTF-8
- Boolean:存儲一個布爾值,true或false
- Integer:整數可以是32位或64位,這取決于伺服器
- Double:存儲浮點值
- Arrays:數組或清單,多個值存儲到一個鍵
- Object:用于嵌入式的文檔,即一個值為一個文檔
- Null:存儲Null值
- Timestamp:時間戳,表示從1970-1-1到現在的總秒數
- Date:存儲目前日期或時間的UNIX時間格式
- 建立日期語句如下
- 注意:參數的格式為YYYY-MM-DD
new Date('2017-12-20')
特殊的object id
- 每個文檔都有一個屬性,為_id,保證每個文檔的唯一性
- 可以自己去設定_id插入文檔
- 如果沒有提供,那麼MongoDB為每個文檔提供了一個獨特的_id,類型為objectID
- objectID是一個12位元組的十六進制數
- 前4個位元組為目前時間戳
- 接下來3個位元組的機器ID
- 接下來的2個位元組中MongoDB的服務程序id
- 最後3個位元組是簡單的增量值
1.6資料增删改
1.6.1插入- 文法
db.集合名稱.insert(document)
- 插入文檔時,如果不指定_id參數,MongoDB會為文檔配置設定一個唯一的ObjectId
- 例1
db.stu.insert({name:'gj',gender:1})
- 例2
s1={_id:'20160101',name:'hr'}
s1.gender=0
db.stu.insert(s1)
簡單查詢 - 文法
db.集合名稱.find()
1.6.2更新
- 文法
db.集合名稱.update(
<query> ,<update>,{multi: <boolean>}
)
- 參數query:查詢條件,類似sql語句update中where部分
- 參數update:更新操作符,類似sql語句update中set部分
- 參數multi:可選,預設是false,表示隻更新找到的第一條記錄,值為true表示把滿足條件的文檔全部更新
- 例3:全文檔更新
db.stu.update({name:'hr'},{name:'mnc'})
- 例4:指定屬性更新,通過操作符$set
db.stu.insert({name:'hr',gender:0})
db.stu.update({name:'hr'},{$set:{name:'hys'}})
- 例5:修改多條比對到的資料
db.stu.update({},{$set:{gender:0}},{multi:true})
1.6.3儲存
- 文法
db.集合名稱.save(document)
- 如果文檔的_id已經存在則修改,如果文檔的_id不存在則添加
- 例6
db.stu.save({_id:'20160102','name':'yk',gender:1})
- 例7
db.stu.save({_id:'20160102','name':'wyk'})
1.6.4删除
- 文法
db.集合名稱.remove(
<query>,{justOne: <boolean>}
)
- 參數query:可選,删除的文檔的條件(包含即可,不需要完全比對)
- 參數justOne:可選,如果設為true或1,則隻删除一條,預設false,表示删除多條
- 例8:隻删除比對到的第一條
db.stu.remove({gender:0},{justOne:true})
- 例9:全部删除
db.stu.remove({})
關于size的示例
- 例10
- 建立集合
db.createCollection('sub',{capped:true,size:1})
建立示例資料
size:1時僅能插入部分資料;去掉限制可以插入所有資料
- 建立集合stu,文檔的屬性包含:_id、name、hometown、age、gender
- 示例資料如下:
db.stu.drop()
db.stu.insert({name:'郭靖',hometown:'蒙古',age:20,gender:true})
db.stu.insert({name:'黃蓉',hometown:'桃花島',age:18,gender:false})
db.stu.insert({name:'華筝',hometown:'蒙古',age:18,gender:false})
db.stu.insert({name:'黃藥師',hometown:'桃花島',age:40,gender:true})
db.stu.insert({name:'段譽',hometown:'大理',age:16,gender:true})
db.stu.insert({name:'段王爺',hometown:'大理',age:45,gender:true})
db.stu.insert({name:'洪七公',hometown:'華山',age:18,gender:true})
2.資料查詢
2.1基本查詢
- 方法find():查詢
db.集合名稱.find({條件文檔})
- 方法findOne():查詢,隻傳回第一個
db.集合名稱.findOne({條件文檔})
- 方法pretty():将結果格式化
db.集合名稱.find({條件文檔}).pretty()
比較運算符
- 等于,預設是等于判斷,沒有運算符
- 小于$lt
- 小于或等于$lte
- 大于$gt
- 大于或等于$gte
- 不等于$ne
- 例1:查詢名稱等于'郭靖'的學生
db.stu.find({name:'郭靖'})
- 例2:查詢年齡大于或等于18的學生
db.stu.find({age:{$gte:18}})
邏輯運算符
- 查詢時可以有多個條件,多個條件之間需要通過邏輯運算符連接配接
- 邏輯與:預設是邏輯與的關系
- 例3:查詢年齡大于或等于18,并且性别為true的學生
db.stu.find({age:{$gte:18},gender:true})
- 邏輯或:使用$or,值為數組,數組中每個元素為json
- 例4:查詢年齡大于18,或性别為false的學生
db.stu.find({$or:[{age:{$gt:18}},{gender:false}]})
- and和or一起使用
- 例5:查詢年齡大于18或姓名是郭靖,并且性别為男生
db.stu.find({$or:[{age:{$gte:18}},{gender:true}],name:'gj'})
範圍運算符
- 使用"$in","$nin" 判斷是否在某個範圍内
- 例6:查詢年齡為18、28的學生
db.stu.find({age:{$in:[18,28]}})
支援正規表達式
- mongodb提供的終端shell,同時也是一個js的執行器,可以編寫js的代碼和函數
- 使用//或$regex編寫正規表達式
- 例7:查詢姓黃的學生
db.stu.find({name:/^黃/})
db.stu.find({name:{$regex:'^黃'}})
自定義查詢
- 使用$where後面寫一個函數,傳回滿足條件的資料
- 例7:查詢年齡大于30的學生
db.stu.find({
$where:function() {
return this.age>30;
}
})
2.2Limit
- 方法limit():用于讀取指定數量的文檔
- 文法:
db.集合名稱.find().limit(NUMBER)
- 參數NUMBER表示要擷取文檔的條數
- 如果沒有指定參數則顯示集合中的所有文檔
- 例1:查詢2條學生資訊
db.stu.find().limit(2)
skip
- 方法skip():用于跳過指定數量的文檔
- 文法:
db.集合名稱.find().skip(NUMBER)
- 參數NUMBER表示跳過的記錄條數,預設值為0
- 例2:查詢從第3條開始的學生資訊
db.stu.find().skip(2)
一起使用
- 方法limit()和skip()可以一起使用,不分先後順序
- 建立資料集
for(i=0;i<15;i++){
db.t1.insert({_id:i})
}
- 查詢第5至8條資料
db.stu.find().limit(4).skip(5)
或
db.stu.find().skip(5).limit(4)
2.3投影
mongodb投影意義是隻選擇需要的資料,而不是選擇整個一個文檔的資料。如果一個文檔有5個字段,隻需要顯示3個,隻從中選擇3個字段。
find()方法,查詢文檔接收的第二個可選的參數是要檢索的字段清單。當執行find()方法,那麼它會顯示一個文檔的所有字段。要限制這一點,需要設定字段清單值為1或0。1是用來顯示字段,而0被用來隐藏字段。
文法
find()方法的基本文法如下
>db.COLLECTION_NAME.find({},{KEY:1})
例子:考慮集合 myycol 有下列資料
{ "_id" : ObjectId(5983548781331adf45ec5), "title":"MongoDB Overview"}
{ "_id" : ObjectId(5983548781331adf45ec6), "title":"NoSQL Overview"}
{ "_id" : ObjectId(5983548781331adf45ec7), "title":"Yiibai Yiibai Overview"}
下面的例子将顯示文檔的标題,在查詢文檔時。
>db.mycol.find({},{"title":1,_id:0})
{"title":"MongoDB Overview"}
{"title":"NoSQL Overview"}
{"title":"Yiibai Yiibai Overview"}
>
請注意在執行find()方法時_id字段始終顯示,如果不想要顯示這個字段,那麼需要将其設定為0
2.4排序
- 方法sort(),用于對結果集進行排序
- 文法
db.集合名稱.find().sort({字段:1,...})
- 參數1為升序排列
- 參數-1為降序排列
- 例1:根據性别降序,再根據年齡升序
db.stu.find().sort({gender:-1,age:1})
2.5統計個數
- 方法count()用于統計結果集中文檔條數
- 文法,使用find後跟count()
db.集合名稱.find({條件}).count()
- 也可以與為
db.集合名稱.count({條件})
- 例1:統計男生人數
db.stu.find({gender:true}).count()
- 例2:統計年齡大于20的男生人數
db.stu.count({age:{$gt:20},gender:true})
2.6消除重複
- 方法distinct()對資料進行去重
- 文法
db.集合名稱.distinct('去重字段',{條件})
- 例:查找年齡大于18的學生,來自哪些省份
db.stu.distinct('hometown',{age:{$gt:18}})
3.聚合 aggregate
- 聚合(aggregate)主要用于計算資料,類似sql中的聚合函數sum()、avg()
- 文法
db.集合名稱.aggregate({管道:{表達式}})
管道
- 管道在Unix和Linux中一般用于将目前指令的輸出結果作為下一個指令的輸入
ps ajx | grep mongo
- 在mongodb中,管道具有同樣的作用,文檔處理完畢後,通過管道進行下一次處理
- 常用管道
- $group:将集合中的文檔分組,可用于統計結果
- $match:過濾資料,隻輸出符合條件的文檔
- $project:修改輸入文檔的結構,如重命名、增加、删除字段、建立計算結果
- $sort:将輸入文檔排序後輸出
- $limit:限制聚合管道傳回的文檔數
- $skip:跳過指定數量的文檔,并傳回餘下的文檔
- $unwind:将數組類型的字段進行拆分
表達式
- 處理輸入文檔并輸出
- 文法
表達式:'$列名'
- 常用表達式
- $sum:計算總和,$sum:1 表示以一倍計數
- $avg:計算平均值
- $min:擷取最小值
- $max:擷取最大值
- $push:在結果文檔中插入值到一個數組中
- $first:根據資源文檔的排序擷取第一個文檔資料
- $last:根據資源文檔的排序擷取最後一個文檔資料
3.1$group
- 将集合中的文檔分組,可用于統計結果
- _id表示分組的依據,使用某個字段的格式為'$字段'
- 例1:統計男生、女生的總人數
db.stu.aggregate(
{$group:
{
_id:'$gender',
counter:{$sum:1}
}
}
)
Group by null
- 将集合中所有文檔分為一組
- 例2:求學生總人數、平均年齡
db.stu.aggregate(
{$group:
{
_id:null,
counter:{$sum:1},
avgAge:{$avg:'$age'}
}
}
)
透視資料
- 例3:統計學生性别及學生姓名
db.stu.aggregate(
{$group:
{
_id:'$gender',
name:{$push:'$name'}
}
}
)
- 使用$$ROOT可以将文檔内容加入到結果集的數組中,代碼如下
db.stu.aggregate(
{$group:
{
_id:'$gender',
name:{$push:'$$ROOT'}
}
}
)
3.2 $match
- 用于過濾資料,隻輸出符合條件的文檔
- 使用MongoDB的标準查詢操作
- 例1:查詢年齡大于20的學生
db.stu.aggregate(
{$match:{age:{$gt:20}}}
)
- 例2:查詢年齡大于20的男生、女生人數
db.stu.aggregate(
{$match:{age:{$gt:20}}},
{$group:{_id:'$gender',counter:{$sum:1}}}
)
3.3 $project
- 修改輸入文檔的結構,如重命名、增加、删除字段、建立計算結果
- 例1:查詢學生的姓名、年齡
db.stu.aggregate(
{$project:{_id:0,name:1,age:1}}
)
- 例2:查詢男生、女生人數,輸出人數
db.stu.aggregate(
{$group:{_id:'$gender',counter:{$sum:1}}},
{$project:{_id:0,counter:1}}
)
3.4 $sort
- 将輸入文檔排序後輸出
- 例1:查詢學生資訊,按年齡升序
b.stu.aggregate({$sort:{age:1}})
- 例2:查詢男生、女生人數,按人數降序
db.stu.aggregate(
{$group:{_id:'$gender',counter:{$sum:1}}},
{$sort:{counter:-1}}
)
3.5 $limit
- 限制聚合管道傳回的文檔數
- 例1:查詢2條學生資訊
db.stu.aggregate({$limit:2})
$skip
- 跳過指定數量的文檔,并傳回餘下的文檔
- 例2:查詢從第3條開始的學生資訊
db.stu.aggregate({$skip:2})
- 例3:統計男生、女生人數,按人數升序,取第二條資料
db.stu.aggregate(
{$group:{_id:'$gender',counter:{$sum:1}}},
{$sort:{counter:1}},
{$skip:1},
{$limit:1}
)
- 注意順序:先寫skip,再寫limit
3.6 $unwind
- 将文檔中的某一個數組類型字段拆分成多條,每條包含數組中的一個值
文法1
- 對某字段值進行拆分
db.集合名稱.aggregate({$unwind:'$字段名稱'})
- 構造資料
db.t2.insert({_id:1,item:'t-shirt',size:['S','M','L']})
- 查詢
db.t2.aggregate({$unwind:'$size'})
文法2
- 對某字段值進行拆分
- 處理空數組、非數組、無字段、null情況
- 屬性preserveNullAndEmptyArrays值為false表示丢棄屬性值為空的文檔
- 屬性preserveNullAndEmptyArrays值為true表示保留屬性值為空的文檔
db.inventory.aggregate({
$unwind:{
path:'$字段名稱',
preserveNullAndEmptyArrays:<boolean> #防止資料丢失
}
})
- 構造資料
db.t3.insert([
{ "_id" : 1, "item" : "a", "size": [ "S", "M", "L"] },
{ "_id" : 2, "item" : "b", "size" : [ ] },
{ "_id" : 3, "item" : "c", "size": "M" },
{ "_id" : 4, "item" : "d" },
{ "_id" : 5, "item" : "e", "size" : null }
])
- 使用文法1查詢
db.t3.aggregate({$unwind:'$size'})
- 檢視查詢結果,發現對于空數組、無字段、null的文檔,都被丢棄了
- 問:如何能不丢棄呢?
- 答:使用文法2查詢
db.t3.aggregate({$unwind:{path:'$size',preserveNullAndEmptyArrays:true}})
4.索引
- 在mysql中已經學習了索引,并知道索引對于查詢速度的提升
- mongodb也支援索引,以提升查詢速度
步驟一:建立大量資料
- 在指令行中執行如下代碼,向集合中插入10萬條文檔
- 注意:不要在圖形界面中執行,因為軟體原因無法插入10萬條資料就會中斷執行
for(i=0;i<100000;i++){
db.t1.insert({name:'test'+i,age:i})
}
步驟二:資料查找性能分析
- 查找姓名為'test10000'的文檔
db.t1.find({name:'test10000'})
- 使用explain()指令進行查詢性能分析
db.t1.find({name:'test10000'}).explain('executionStats')
- 其中的executionStats下的executionTimeMillis表示整體查詢時間,機關是毫秒
- 性能分析結果如下圖,由于機器的配置原因這個時間也會不同
步驟三:建立索引
- 建立索引
- 1表示升序,-1表示降序
db.集合.ensureIndex({屬性:1})
如
db.t1.ensureIndex({name:1})
步驟四:對索引屬性查詢
- 執行上面的同樣的查詢,并進行查詢性能分析
db.t1.find({name:'test10000'}).explain('executionStats')
- 性能分析結果如下圖
索引的指令
- 建立唯一索引,實作唯一限制的功能
db.t1.ensureIndex({"name":1},{"unique":true})
- 聯合索引,對多個屬性建立一個索引,按照find()出現的順序
db.t1.ensureIndex({name:1,age:1})
- 檢視文檔所有索引
db.t1.getIndexes()
- 删除索引
db.t1.dropIndex('索引名稱')
5.備份與恢複
5.1備份
- 文法
mongodump -h dbhost -d dbname -o dbdirectory
- -h:伺服器位址,也可以指定端口号
- -d:需要備份的資料庫名稱
- -o:備份的資料存放位置,此目錄中存放着備份出來的資料
- 例1
sudo mkdir test1bak
sudo mongodump -h 192.168.196.128:27017 -d test1 -o ~/Desktop/test1bak
5.2恢複
- 文法
mongorestore -h dbhost -d dbname --dir dbdirectory
- -h:伺服器位址
- -d:需要恢複的資料庫執行個體
- --dir:備份資料所在位置
- 例2
mongorestore -h 192.168.196.128:27017 -d test2 --dir ~/Desktop/test1bak/test1
6.賬戶管理
6.1超級管理者
- 為了更加安全的通路 mongodb,需要通路者提供使用者名和密碼,于是需要在mongodb 中建立使用者
- 采用了角色-使用者-資料庫的安全管理方式
- 常用的的系統角色有:
- root: 隻在 admin 資料中可使用,超級賬戶,超級權限
- Read: 允許使用者讀取指定的資料庫
- readWrite: 允許使用者讀寫指定的資料庫
- 建立超級使用者
use admin
db.createUser(
{
user: 'admin',
pwd: '123',
roles:[{role:'root',db:'admin'}]
}
)
6.2啟用安全認證
- 修改配置檔案
sudo vi /etc/mongod.conf
- 啟用身份驗證
- 注意: keys 和 values 之間一定要加空格,否則會解析報錯
security:
authorization enabled
- 重新開機服務
sudo service mongod restart
- 使用認證某個資料方式終端連接配接
mongo -u admin -p 123 --authenticationDatabase admin
6.3普通使用者管理
- 使用超級管理者登入,然後進入使用者管理操作
- 檢視目前資料庫的使用者
use demo
show users
- 建立普通 使用者
db.createUser(
{
user: 'xingyeah',
pwd: '123',
roles:[{role:'readWrite',db:'demo'}]
}
)
- 退出 root 連接配接 使用 xignyeah 登入
mongo -u xingyeah -p 123 --authenticationDatabase python_info
- 切換資料庫,執行指令檢視效果
- 修改 yoghurt:可以修改密碼, 或者roles 屬性
# 修改密碼
db.updateUser('xingyeah',{pwd: '456'})
# 修改屬性
db.updateUser('xingyeah',{roles:[{role: 'read',db:'demo'}]})
7.與Python互動
CC是誰:Python+mongo的使用(連接配接、增删改查)zhuanlan.zhihu.com