MongoDB基础知识总结
一、安裝
Linux:
? 命令安裝
? sudo apt install -y mongodb-org
? 源碼安裝
? 下載源碼——解壓——移動(dòng)到/usr/local/目錄下——在shell的初始化腳本.bashrc中添加mongodb可執(zhí)行文件到環(huán)境變量path中。(在.bashrc文件的最后添加export PATH=/usr/local/mongodb/bin:$PATH)
二、簡(jiǎn)單使用
默認(rèn)端口:27017
默認(rèn)配置文件的位置:/etc/mongodb.conf
默認(rèn)日志的位置:/var/log/mongodb/mongodb.log
啟動(dòng)方式:
? 本地測(cè)試方式啟動(dòng),只具有本地?cái)?shù)據(jù)增刪改查的功能,主要是驗(yàn)證數(shù)據(jù)庫(kù)是否能正常運(yùn)行
? 生產(chǎn)環(huán)境啟動(dòng),具有完整的全部功能,服務(wù)器部署啟動(dòng)
本地測(cè)試方式啟動(dòng):
? 啟動(dòng) sudo service mongodb start
? 停止 sudo service mongodb stop
? 重啟 sudo service mongodb restart
生產(chǎn)環(huán)境正式的啟動(dòng)方式:
? sudo mongod 可選參數(shù)
? 只以sudo mongod 命令啟動(dòng)時(shí),默認(rèn)將數(shù)據(jù)存放在了/data/db目錄下,需要手動(dòng)創(chuàng)建
? 可選參數(shù):
? --dbpath=數(shù)據(jù)庫(kù)存放路徑(絕對(duì)路徑)
? --logpath=日志文件的存放路徑,重啟后日志會(huì)覆蓋原來的日志,不是追加寫入
? 在后面添加–append或者–logappend 可以設(shè)置日志的寫入形式為追加模式
? --fork或者-fork 在當(dāng)前進(jìn)程下開啟新的子進(jìn)程運(yùn)行mongodb服務(wù),一旦開啟成功,父進(jìn)程就會(huì)退出
? --auth 以權(quán)限認(rèn)證的方式啟動(dòng)
? -f 配置文件名 可以將上述的配置信息寫入到文件,然后通過該文件中的參數(shù)進(jìn)行加載啟動(dòng)
? 例如配置文件這樣寫:
? dbpath=數(shù)據(jù)庫(kù)存放路徑
? logpath=日志文件的存放路徑
? logappend=true(注意不能寫append)
? fork=true
? auth=true
啟動(dòng)mongodb的客戶端:
? 啟動(dòng)本地客戶端 mongo
? 退出 exit或者ctrl+c
? 查看幫助 mongo --help
數(shù)據(jù)庫(kù)的操作
? 查看當(dāng)前的數(shù)據(jù)庫(kù) db (沒有切換數(shù)據(jù)庫(kù)的情況下默認(rèn)使用test數(shù)據(jù)庫(kù))
? 查看所有的數(shù)據(jù)庫(kù) show dbs或者show databases (看不到test數(shù)據(jù)庫(kù)是因?yàn)榇藬?shù)據(jù)庫(kù)不在磁盤中,而是在內(nèi)存中,只能查看磁盤中存在的數(shù)據(jù)庫(kù))
? 切換數(shù)據(jù)庫(kù) use 數(shù)據(jù)庫(kù)名,如果數(shù)據(jù)庫(kù)不存在,則創(chuàng)建數(shù)據(jù)庫(kù),否則切換到指定數(shù)據(jù)庫(kù)。創(chuàng)建之后show dbs并不能顯示出來,需要往里面插入數(shù)據(jù)(db.集合名.insert({key:value}) 集合若不存在會(huì)自動(dòng)創(chuàng)建)或者創(chuàng)建一個(gè)集合才能將其顯示出來
? 刪除當(dāng)前的數(shù)據(jù)庫(kù) dp.dropDatabase()
集合的操作
集合類似于mysql中的表
查看所有集合 show collections 當(dāng)沒有數(shù)據(jù)時(shí)是看不到集合的,需要先插入數(shù)據(jù)
顯示的創(chuàng)建集合 db.createCollection(名字,可選參數(shù))
? db.createCollection(“sub”,{capped:true,size:10})
? capped默認(rèn)為false,表示不設(shè)置上限;size表示集合所占用的字節(jié)數(shù),當(dāng)capped為true時(shí)需要設(shè)置此參數(shù),當(dāng)文檔達(dá)到上限時(shí),寫入數(shù)據(jù)會(huì)將之前的數(shù)據(jù)覆蓋,先覆蓋最早插入的(size的值小于等于256時(shí),實(shí)際上都為256)
? 有上限的集合數(shù)據(jù)不允許被修改,且查詢速度也會(huì)相對(duì)較快
查看集合是否有上限 db.集合名.isCapped() false無上限,true有上限
查看集合的數(shù)據(jù) db.集合名.find()
刪除集合 db.集合名.drop()
三、常見數(shù)據(jù)類型
Object ID:文檔/數(shù)據(jù)的ID,是數(shù)據(jù)的主鍵,默認(rèn)會(huì)創(chuàng)建索引
String:字符串,最常用,必須是有效的UTF-8
Boolean:布爾值,true或者false,必須是小寫
Integer:整數(shù),32或者64位,取決于服務(wù)器
Double:(雙精度)浮點(diǎn)數(shù)
Arrays:數(shù)組、列表
Object:mongodb中的一條數(shù)據(jù)(文檔),即文檔嵌套文檔
Null:空值
Timestamp:時(shí)間戳,表示從1970-1-1到現(xiàn)在的秒數(shù)
Date:存儲(chǔ)當(dāng)前日期或者時(shí)間的UNIX時(shí)間格式
注意:每個(gè)文檔都有一個(gè)屬性為_id,保證了每個(gè)文檔的唯一性,mongodb默認(rèn)使用其作為主鍵,其值可以手動(dòng)設(shè)置,如果沒有設(shè)置,MongoDB為每個(gè)文檔提供了一個(gè)獨(dú)特的值,類型為ObjectID
ObjectID是一個(gè)12字節(jié)的十六進(jìn)制數(shù),每個(gè)字節(jié)占兩位,一共是24位(十六進(jìn)制的數(shù)字字符串)
? 前四個(gè)字節(jié)(前八位):當(dāng)前時(shí)間戳
? 接下來的三個(gè)字節(jié)(六位):機(jī)器的ID
? 接下來的兩個(gè)字節(jié)(四位):MongoDB的服務(wù)進(jìn)程ID
? 最后三個(gè)字節(jié)(六位):簡(jiǎn)單的增量值
四、增刪改查
插入數(shù)據(jù)
方式一
db.集合名.insert({key:value}) key可以不加引號(hào),終端會(huì)自動(dòng)添加,value是數(shù)字不加引號(hào),字符串必須加引號(hào)
db.集合名.insert([{},{},{}…]) 批量插入
如果想修改_id的值,插入數(shù)據(jù)時(shí)將其作為key,值作為value,放到要插入的一條數(shù)據(jù)(即文檔)前面即可
? 如:db.集合名.insert({_id:“值”,key:value})
方式二
db.集合名.save(_id:值,key:value) 如果id值已經(jīng)存在且其他數(shù)據(jù)不同則修改(會(huì)把原來數(shù)據(jù)全部刪除,更新為新數(shù)據(jù)),如果id值不存在則添加新數(shù)據(jù)
db.集合名.save(key:value) MongoDB會(huì)指定id
查詢數(shù)據(jù)
db.集合名.find() 會(huì)查詢?nèi)繑?shù)據(jù)
? db.集合名.find({條件文檔})
db.集合名.findOne() 只返回第一個(gè)
? db.集合名.findOne({條件文檔})
db.集合名.pretty() 將結(jié)果格式化,不能和findOne()一起使用
? db.集合名.find({條件文檔}).pretty()
條件文檔:
比較運(yùn)算符
? 等于:默認(rèn)就是等于判斷,沒有運(yùn)算符
? 小于:$lt 也就是less than
? 小于等于:$lte 也就是less than euqal
? 大于:$gt 也就是greater than
? 大于等于:$gte 也就是greater than equal
? 不等于:$ne 也就是no equal
? db.stu.find({age:{$gte:18}}) 查詢年齡大于等于18的所有學(xué)生
邏輯運(yùn)算符
? and:$and
? 或者直接在一個(gè){}中寫多個(gè)條件即可
? or:$or 值為數(shù)組(列表),數(shù)組中的每個(gè)元素為json,代表一個(gè)條件
? db.stu.find({age:{$lt:18},gender:‘male’}) 查詢年齡小于18,性別為male的所有學(xué)生
? db.stu.find({KaTeX parse error: Expected '}', got 'EOF' at end of input: or:[{age:{ne:18}},{gende:‘female’}]}) 查詢年齡不等于18或者性別為female的所有學(xué)生
? db.stu.find({KaTeX parse error: Expected '}', got 'EOF' at end of input: or:[{age:{gt:18}},{age:12}],gender:“male”}) 查詢年齡大于18或者年齡等于12并且性別為male的所有 學(xué)生
范圍運(yùn)算符
? $in 查找的數(shù)據(jù)是在數(shù)組內(nèi)
? $nin 查找的數(shù)據(jù)不在數(shù)組內(nèi)
? db.stu.find({age:{$in:[12,23,34]}}) 查詢年齡為12、23、34的所有學(xué)生
正則表達(dá)式
? $regex 一般存的值為字符串時(shí)使用
? db.stu.find({name:{$regex:’^黃’}}) 查詢name以“黃”開頭的所有學(xué)生
自定義查詢
? mongo shell 是一個(gè)js的執(zhí)行環(huán)境,使用$where寫一個(gè)js函數(shù),返回滿足條件的數(shù)據(jù)
? db.stu.find({$where:function(){return this.age>30;}}) 返回年齡大于30的所有學(xué)生,this類似于MySQL的游標(biāo)
對(duì)查詢結(jié)果進(jìn)行操作
skip和limit
? limit(數(shù)字) 讀取指定數(shù)量的文檔
? skip(數(shù)字) 跳過指定數(shù)量的文檔
? skip的優(yōu)先級(jí)高于limit
? db.stu.find().limit(5).skip(5) 跳過前五條數(shù)據(jù),顯示后面的前五條數(shù)據(jù),改變skip和limit的前后順序結(jié)果一樣
投影
? 在查詢到的結(jié)果中只顯示選擇的字段
? db.集合名.find({},{字段名稱:1,字段名稱:1…})
? 前面的空括號(hào)填查詢條件,不寫就是查詢條件為空值為1表示顯示,值為0表示不顯示
? _id列是默認(rèn)顯示的,如果不顯示需要明確設(shè)置為0
? 對(duì)于其他的字段不能既有設(shè)置為0的字段,還有設(shè)置為1的字段
? PS:除了_id之外,想看哪個(gè)字段設(shè)置為1就行啦
排序
? sort()
? db.集合名.find().sort({字段名:1,…}) 1代表升序排列,-1代表降序 排序
? db.stu.find().sort({gender:-1,age:1}) 根據(jù)性別降序排序,當(dāng)性別相同時(shí)再根據(jù)年齡升序排序
統(tǒng)計(jì)個(gè)數(shù)
? count() 統(tǒng)計(jì)查詢結(jié)果集的文檔條數(shù)
? db.集合名.find({條件}).count() 等于db.集合名.count({條件})
去重
? db.集合名.distinct(“字段名”) 只會(huì)顯示此字段名的去重后的所有值,是一個(gè)列表
? db.集合名.distinct(“字段名”,{查詢條件}) 顯示根據(jù)查詢條件查詢出來的值的此字段名的去重后的所有值
顯示操作的詳細(xì)信息
db.集合名.find().explain(“executionStats”) 可以查看操作的執(zhí)行時(shí)間等各種信息
更新數(shù)據(jù)
? db.集合名.update({查詢條件},{更新操作},{multi:true/false})
? multi為可選參數(shù),默認(rèn)是false,表示只更新找到的第一條數(shù)據(jù),true表示更新滿足條件的全部數(shù)據(jù)
? db.stu.update({name:“hr”},{name:“mc”}) 會(huì)把找到的name為hr的第一條數(shù)據(jù)的name改為mc,并且會(huì)把其他的字 段值刪除
? db.stu.update({name:“hr”},{$set:{name:“mc”}}) 會(huì)把找到的name為hr的第一條數(shù)據(jù)的name改為mc,其他值不變
? db.stu.update({},{$set:{gender:“female”}},{multi:true}) 把全部學(xué)生的性別改為female
? PS:multi:true必須和$set一起使用!
? upsert參數(shù)
? db.stu.update({name:“l(fā)iu”},{$set:{age:1000}},{upsert:true}) 查詢name為liu的第一條數(shù)據(jù),如果其age值已經(jīng)是1000 則不做任何操作,如果不是則更新age的值為1000,若不存在age字段則添加此字段,如果查找失敗則插入此條數(shù)據(jù)
? 同時(shí)使用multi和upsert的話,要把它們寫到一個(gè)大括號(hào)里面,逗號(hào)隔開
刪除數(shù)據(jù)
? db.集合名.remove({查詢條件},{justOne:true/false})
? justOne可選,默認(rèn)是false,表示刪除全部,為true或1表示只刪除查找到的第一條數(shù)據(jù)
? db.集合名.remove({}) 刪除此集合中的全部數(shù)據(jù),即使查詢條件為空,第一個(gè)查詢條件的{}也不能省略
五、聚合操作
聚合(aggregate)是基于數(shù)據(jù)處理的聚合管道,每個(gè)文檔通過一個(gè)由多個(gè)階段(stage)組成的管道,可以對(duì)每個(gè)階段的管道進(jìn)行分組、過濾等,然后經(jīng)處理,輸出相應(yīng)的結(jié)果
db.集合名.aggregate({管道命令:{表達(dá)式}})
一個(gè){}是一個(gè)管道
前一個(gè)管道的輸出結(jié)果作為下一個(gè)管道的輸入
常用管道命令
在mongodb中,文檔處理完畢后,通過管道進(jìn)行下一次處理
$group:將集合中的文檔分組,可用于統(tǒng)計(jì)結(jié)果
$match:過濾數(shù)據(jù),只輸出符合條件的文檔
$project:修改輸入文檔的結(jié)構(gòu),如重命名、增加、刪除字段、創(chuàng)建計(jì)算結(jié)果
$sort:將輸入文檔排序后輸出
$limit:限制聚合管道返回的文檔數(shù)
$skip:跳過指定數(shù)量的文檔,并返回余下的文檔
$unwind:拆分指定的字段,爬蟲用得不多
常用表達(dá)式
表達(dá)式用來處理輸入文檔并輸出
語法:表達(dá)式:’$列名’
sum:計(jì)算總和,sum:計(jì)算總和,sum:計(jì)算總和,sum:1 表示以一倍進(jìn)行個(gè)數(shù)的統(tǒng)計(jì)
$avg:計(jì)算平均值
$min:獲取最小值
$max:獲取最大值
$push:在結(jié)果的指定值插入到一個(gè)數(shù)組中
$group
db.stu.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:'gender’,sum_age:{sum:‘sum:‘sum:‘age’},name_list:{push:′push:'push:′name’}}}) _id表示以什么字段進(jìn)行分組,其他的字段名可以 自己任意寫,結(jié)果是將學(xué)生安裝gender分組,并且計(jì)算每組的年齡總和,把每組的名字存到名為name_list的列表中
或者可以把整個(gè)文檔分為一組進(jìn)行統(tǒng)計(jì),查詢顯示出來的是全部文檔數(shù)據(jù)
db.stu.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: …:null,counter:{sum:1}}}) 相當(dāng)于db.stu.find().count()
數(shù)據(jù)透視
db.stu.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: …_id:null,name:{push:’$name’}}}) 把所有name放到一個(gè)列表里
db.stu.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: …null,data_stu:{push:’$$ROOT’}}}) 將整個(gè)文檔放入數(shù)組中
$match
和find的區(qū)別就是$match過濾出來的結(jié)果可以作為下一個(gè)管道的輸入
$match的值可以是前面提到的五種查詢方式
db.stu.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: match:{age:{gt:20}}}) 查詢年齡大于20的學(xué)生
db.stu.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: match:{age:{gt:20}}},{KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"gender",counter:{$sum:1}}}) 查詢年齡大于20的男生和女生的人數(shù)
$project
類似于投影操作,輸出的結(jié)果每一條數(shù)據(jù)都在一個(gè){}中
db.stu.aggregate({$project:{_id:0,name:1,age:1}}) 僅輸出學(xué)生的年齡和姓名
db.stu.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: …nder",counter:{sum:1}}},{$project:{_id:0,counter:1}}) 查詢男生和女生的人數(shù),僅輸出人數(shù)
$sort
db.stu.aggregate({$sort:{age:1}}) 查詢學(xué)生信息,按照年齡升序輸出
db.stu.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: …nder",counter:{sum:1}}},{$sort:{counter:-1}}) 查詢男生和女生人數(shù),按照人數(shù)降序輸出
limit和limit和limit和skip
注意和在find()中使用時(shí)的區(qū)別
db.stu.aggregate({KaTeX parse error: Expected 'EOF', got '}' at position 8: limit:2}?,{skip:1}) 會(huì)只顯示第二條數(shù)據(jù)
db.stu.aggregate({KaTeX parse error: Expected 'EOF', got '}' at position 7: skip:1}?,{limit:2}) 會(huì)只顯示第二條和第三條數(shù)據(jù)
$unwind
拆分,了解即可
db.集合名.aggregate({KaTeX parse error: Expected '}', got 'EOF' at end of input: unwind:{path:"你要拆分的字段名",preserveNullAndEmptyArrays:true})
六、索引
索引:加快查詢速度;進(jìn)行數(shù)據(jù)的去重
創(chuàng)建索引后會(huì)把原先的數(shù)據(jù)結(jié)構(gòu)進(jìn)行調(diào)整,調(diào)整后的結(jié)構(gòu)類似于二叉排序樹,查詢效率是O(logn)
創(chuàng)建索引
db.集合名.ensureIndex({屬性:1or-1}) 1表示升序,-1表示降序
查看索引
默認(rèn)情況下_id是集合的索引
db.集合名.getIndexes()
刪除索引
db.集合名.dropIndex({“索引名稱”:1})
創(chuàng)建唯一索引
在插入數(shù)據(jù)時(shí)會(huì)檢查一下數(shù)據(jù)是否已經(jīng)存在,存在則插入失敗
會(huì)降低插入速度
db.集合名.ensureIndex({“字段名”:1},{“unique”:true})
建立復(fù)合索引
db.collection_name.ensureIndex({字段1:1,字段2:1}) 最左原則(用字段1查詢使用索引,用字段1和字段2一起查詢使用索引,但是用字段2查詢不會(huì)使用索引)
注意點(diǎn):
根據(jù)需要選擇是否需要?jiǎng)?chuàng)建唯一索引
索引字段是升序還是降序在單個(gè)索引的情況下不影響查詢效率,但是帶復(fù)合索引的條件下會(huì)有影響
數(shù)據(jù)量巨大并且數(shù)據(jù)庫(kù)的讀出操作非常頻繁時(shí)才需要?jiǎng)?chuàng)建索引,如果寫入操作頻繁,創(chuàng)建索引會(huì)影響寫入速度
PS:在查詢時(shí)如果字段1需要升序的方式排序輸出,字段2需要降序的方式排序輸出,那么此時(shí)復(fù)合索引的建立需要把字段1設(shè)置為1,字段2設(shè)置為-1
一般在讀寫操作都非常頻繁且數(shù)據(jù)量巨大時(shí)采用讀寫分離的策略
七、權(quán)限管理
剛安裝的MongoDB默認(rèn)不使用權(quán)限認(rèn)證方式啟動(dòng),而且在安裝的時(shí)候并沒有設(shè)置權(quán)限,而公網(wǎng)運(yùn)行時(shí)需要設(shè)置權(quán)限以保證數(shù)據(jù)安全。
MongoDB沒有默認(rèn)的管理員賬號(hào),所以要先添加管理員賬號(hào),并且MongoDB服務(wù)器需要在運(yùn)行的時(shí)候開啟驗(yàn)證模式。
用戶只能在用戶所在的數(shù)據(jù)庫(kù)登錄(創(chuàng)建用戶的數(shù)據(jù)庫(kù)),包括管理員賬號(hào)。
管理員可以管理所有的數(shù)據(jù)庫(kù),但是不能直接管理其他數(shù)據(jù)庫(kù),要先認(rèn)證后才可以。
創(chuàng)建超級(jí)用戶
先殺死m(xù)ongod進(jìn)程
再以權(quán)限認(rèn)證的方式啟動(dòng)mongodb服務(wù)端
sudo mongod --auth 或者將auth=true寫入配置文件,sudo mongod -f 配置文件名,這樣啟動(dòng)
打開客戶端,mongo,此時(shí)執(zhí)行數(shù)據(jù)庫(kù)各種語句會(huì)報(bào)權(quán)限錯(cuò)誤,需要認(rèn)證才能執(zhí)行操作
use admin 切換數(shù)據(jù)庫(kù)(名字必須是admin)
db.createUser({“user”:“用戶名”,“pwd”:“密碼”,“roles”:[“root”]}) 添加超級(jí)管理員
登錄管理員
use admin 由于是在admin數(shù)據(jù)庫(kù)上創(chuàng)建的用戶,因此必須切換到此數(shù)據(jù)庫(kù)上(用戶創(chuàng)建在哪個(gè)數(shù)據(jù)庫(kù)上就切換到哪個(gè)數(shù)據(jù)庫(kù))
db.auth(“用戶名”,“密碼”) 顯示為1則登錄成功,為0則登錄失敗
登錄成功后就能正常執(zhí)行語句啦
創(chuàng)建普通用戶
在使用的數(shù)據(jù)庫(kù)上創(chuàng)建普通用戶
若添加了超級(jí)管理員,且以權(quán)限認(rèn)證方式登錄,必須先認(rèn)證后才能創(chuàng)建
use test1
db.createUser({“user”:“user1”,“pwd”:“user1”,“roles”:[“read”]}) 如果是readWrite,則是讀寫權(quán)限
show users 查看當(dāng)前數(shù)據(jù)庫(kù)中的用戶情況
在admin數(shù)據(jù)庫(kù)上創(chuàng)建普通用戶
由于在每個(gè)數(shù)據(jù)庫(kù)上面都創(chuàng)建一個(gè)用戶有些繁瑣,因此一般大多數(shù)情況下都把用戶創(chuàng)建在admin數(shù)據(jù)庫(kù)上面
use admin
先認(rèn)證管理員權(quán)限 db.auth(“python”:“python”)
添加普通用戶
db.createUser({user:“user2”,pwd:“user2”,roles:[{db:“test2”,role:“read”},{db:“test3”,role:“readWrite”}]})
這里user2用戶在test2數(shù)據(jù)庫(kù)上的權(quán)限為讀,在test3上的權(quán)限為讀寫
PS:登錄user2用戶時(shí)要在admin數(shù)據(jù)庫(kù)下登錄,因?yàn)槭窃谶@個(gè)數(shù)據(jù)庫(kù)上面創(chuàng)建的此用戶!
刪除用戶
登錄超級(jí)管理員的情況下才能刪除其他用戶
先進(jìn)入賬號(hào)數(shù)據(jù)所在的數(shù)據(jù)庫(kù)
db.dropUser(“用戶名”) 刪除用戶
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的MongoDB基础知识总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python闭包的使用
- 下一篇: 机器学习中常见的希腊字母