一、MongoDB數(shù)據(jù)庫基礎(chǔ)
1.什么是MongoDB數(shù)據(jù)庫
MongoDB 是由C ++語言編寫的,是一個(gè)基于分布式文件存儲(chǔ)的開源數(shù)據(jù)庫系統(tǒng)。在高負(fù)載的情況下,添加更多的節(jié)點(diǎn),可以保證服務(wù)器性能。MongoDB 旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案。
MongoDB將數(shù)據(jù)存儲(chǔ)為一個(gè)文檔,數(shù)據(jù)結(jié)構(gòu)由鍵值(key => value)對(duì)組成.MongoDB文檔類似于JSON對(duì)象。字段值可以包含其他文檔,數(shù)組及文檔數(shù)組。
- MongoDB與傳統(tǒng)數(shù)據(jù)庫之間的區(qū)別
① 傳統(tǒng)型數(shù)據(jù)庫: 結(jié)構(gòu)化數(shù)據(jù), 定好了表結(jié)構(gòu)后,每一行的內(nèi)容,必是符合表結(jié)構(gòu)的,就是說--列的個(gè)數(shù),類型都一樣.
② mongo文檔型數(shù)據(jù)庫: 表下的每篇文檔,都可以有自己獨(dú)特的結(jié)構(gòu)(json對(duì)象都可以有自己獨(dú)特的屬性和值)
MongoDB是文檔類型的數(shù)據(jù)庫。存儲(chǔ)類型是文檔(BSon)[即json的二進(jìn)制化]

2.主要特點(diǎn)
MongoDB 是一個(gè)面向文檔存儲(chǔ)的數(shù)據(jù)庫,操作起來比較簡(jiǎn)單和容易。
你可以在MongoDB記錄中設(shè)置任何屬性的索引(如:FirstName="Sameer",Address="8 Gandhi Road")來實(shí)現(xiàn)更快的排序。
你可以通過本地或者網(wǎng)絡(luò)創(chuàng)建數(shù)據(jù)鏡像,這使得MongoDB有更強(qiáng)的擴(kuò)展性。
如果負(fù)載的增加(需要更多的存儲(chǔ)空間和更強(qiáng)的處理能力) ,它可以分布在計(jì)算機(jī)網(wǎng)絡(luò)中的其他節(jié)點(diǎn)上這就是所謂的分片。
Mongo支持豐富的查詢表達(dá)式。查詢指令使用JSON形式的標(biāo)記,可輕易查詢文檔中內(nèi)嵌的對(duì)象及數(shù)組。
MongoDb 使用update()命令可以實(shí)現(xiàn)替換完成的文檔(數(shù)據(jù))或者一些指定的數(shù)據(jù)字段。
Mongodb中的Map/reduce主要是用來對(duì)數(shù)據(jù)進(jìn)行批量處理和聚合操作。
GridFS是MongoDB中的一個(gè)內(nèi)置功能,可以用于存放大量小文件。
MongoDB允許在服務(wù)端執(zhí)行腳本,可以用Javascript編寫某個(gè)函數(shù),直接在服務(wù)端執(zhí)行,也可以把函數(shù)的定義存儲(chǔ)在服務(wù)端,下次直接調(diào)用即可。
MongoDB支持各種編程語言:RUBY,PYTHON,JAVA,C++,PHP,C#等多種語言。
二、Linux環(huán)境下部署MongoDB
打開官網(wǎng)下載地址:分別對(duì)應(yīng)4個(gè)平臺(tái),windows、Linux、OSX和Solaris
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/
1.官方倉(cāng)庫軟件包介紹
| 包名字 | 描述 |
|---|---|
| mongodb-org | 一個(gè)元數(shù)據(jù)包,將自動(dòng)安裝下面列出的四個(gè)組件軟件包 |
| mongodb-org-server | 包含mongod守護(hù)進(jìn)程和相關(guān)的配置以及init腳本 |
| mongodb-org-mongos | 包含mongos守護(hù)進(jìn)程 |
| mongodb-org-shell | 包含mongo shell 命令行解釋器 |
| mongodb-org-tools | 其他工具 |
mongodb-org-server軟件包提供了一個(gè)mongod以/etc/mongod.conf 配置文件為參照的初始化腳本。
默認(rèn)的配置文件中默認(rèn) bind_ip 設(shè)置為127.0.0.1 這是個(gè)默認(rèn)監(jiān)聽地址。
2.配置包管理系統(tǒng)
2.1mongodb3.6版本
創(chuàng)建一個(gè)/etc/yum.repos.d/mongodb-org-3.6.repo文件,以便您可以直接使用安裝MongoDB yum。
[root@izuf6fuxiq5o2qj8wsqvr3z ~]# vim /etc/yum.repos.d/mongodb-org-3.6.repo
[mongodb-org-3.6]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc
2.2mongodb3.4版本
假如你想安裝 3.4 版本,那么創(chuàng)建 3.4 的倉(cāng)庫文件
# cat /etc/yum.repos.d/mongodb-org-3.4.repo
[mongodb-org-3.4]
name=MongoDB 3.4 Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=0
enabled=1
3.安裝MongoDB軟件包。
sudo yum install -y mongodb-org
- 要安裝特定版本的MongoDB,請(qǐng)分別指定每個(gè)組件包并將版本號(hào)附加到包名稱,如下例所示:
sudo yum install -y mongodb-org-3.6.3 mongodb-org-server-3.6.3 mongodb-org-shell-3.6.3 mongodb-org-mongos-3.6.3 mongodb-org-tools-3.6.3
4.設(shè)置防止意外升級(jí)項(xiàng)
您可以指定任何可用的MongoDB版本。但是yum ,當(dāng)更新的版本可用時(shí),將升級(jí)軟件包。
為防止意外升級(jí),將以下exclude指令添加到您的/etc/yum.conf文件中:
exclude = mongodb-org,mongodb-org-server,mongodb-org-shell,mongodb-org-mongos,mongodb-org-tools
5.啟動(dòng)/按關(guān)閉服務(wù)
# systemctl start mongod
# systemctl enable mongod
# ss -ntal
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:22 *:*
LISTEN 0 1 127.0.0.1:32000 *:*
LISTEN 0 128 127.0.0.1:27017 *:*
# systemctl stop mongod
三、MongoDB數(shù)據(jù)庫簡(jiǎn)單操作
1.MongoDB入門命令
mongo //進(jìn)入當(dāng)前數(shù)據(jù)庫
show dbs //查看mongodb內(nèi)數(shù)據(jù)庫
use databaseName //選庫
show tables/collections //查看當(dāng)前數(shù)據(jù)庫下的表格
1.1 創(chuàng)建數(shù)據(jù)庫
Mongodb的庫是隱式創(chuàng)建,通過use 一個(gè)不存在的庫然后在該庫下創(chuàng)建collection,即可創(chuàng)建庫。
use shop //數(shù)據(jù)庫默認(rèn)直接使用
db.createCollection('user'); //創(chuàng)建關(guān)系表
show collection; //查看數(shù)據(jù)庫內(nèi)表
1.2添加表內(nèi)數(shù)據(jù)
db.user.insert({name:'yy',age:18});
db.user.insert({_id:2 , name:"uni" ,male:"mam"}); //添加內(nèi)容指定id
db.user.insert({_id:3,name:'yuydddu',hobby:['swiming','runing'],intro:{'title':'my name is yutao'}});
//添加非內(nèi)鍵值,可以不匹配
---------------------------------------
db.user.find() //查詢命令
{ "_id" : ObjectId("5c83b9e369b62226da1a2810"), "name" : "yy", "age" : 18 }
{ "_id" : 2, "name" : "uni", "male" : "mam" }
{ "_id" : 3, "name" : "yuydddu", "hobby" : [ "swiming", "runing" ], "intro" : { "title" : "my name is yutao" } }
> db.user.insert({name:'yy',age:18});
- 除此之外collection也是可以隱式創(chuàng)建
db.root.insert({_id:88 , 'name':'yyysii', 'hobby':['like','nnbb'], 'intro':{'title':'mu is like' ,'cotrm':'sss'}}); //隱式創(chuàng)建collection
db.root.find() //查看數(shù)據(jù)庫內(nèi)容
{ "_id" : 88, "name" : "yyysii", "hobby" : [ "like", "nnbb" ], "intro" : { "title" : "mu is like", "cotrm" : "sss" } }
1.3刪除數(shù)據(jù)庫/表
use 該數(shù)據(jù)庫xxx
db.dropDatabase(); //刪除該數(shù)據(jù)庫
db.表名xxx.drop(); //刪除數(shù)據(jù)庫內(nèi)表信息
2.MongoDB--增刪改查
MongoDB存儲(chǔ)的是文檔格式,文檔是json格式的對(duì)象。無論是增刪改查都需要通過json格式進(jìn)行傳遞。
2.1 增操作(insert)
在MongoDB中可以增加單篇、多篇文檔。
db.stu.insert({name:'yy' , num:'92929'});
db,stu.insert({_id:3 ,name:'ydnu' ,num:'egr'}); //指定id
db.stu.insert({name:{x:'li' , ming:'shimin'}, ji:['war','kill']}); //復(fù)雜的單文檔格式。
db.stu.insert([{_id:5 ,name:'yy',hobby:'swim'},{_id:9,num:'99', nem:'df'},{name:'yy'}]); //同時(shí)寫多篇文檔
2.2刪操作 (remove)
db.stu.remove({name:'dd'}); //后加查詢表達(dá)式:選項(xiàng)
db.shenji.remove({male:'n'},true); //每次只刪除一條信息
db.stu.remove() //刪除表內(nèi)所有信息
注意
1: 查詢表達(dá)式依然是個(gè)json對(duì)象
2: 查詢表達(dá)式匹配的行,將被刪掉.
3: 如果不寫查詢表達(dá)式,collections中的所有文檔將被刪掉.
2.3改操作 (update)
db.shenji.update({name:'ff'},{name:'ffy'});
db.shenji.update({name:'ffc'}, {$set:{name:'yy'}});
================ result =============
> db.shenji.find()
{ "_id" : ObjectId("5ca72ff39ff46db4a72f5745"), "name" : "ffy" }
{ "_id" : ObjectId("5ca72ff39ff46db4a72f5746"), "name" : "yy", "male" : "m" }
修改時(shí)的賦值表達(dá)式
:$set 修改某列的值
$unset 刪除某個(gè)列
$rename 重命名某個(gè)列
$inc 增長(zhǎng)某個(gè)列 必須是數(shù)字型
典型實(shí)例
//原數(shù)據(jù)內(nèi)容
> db.xuyou.insert({
... name:'wukong',
... jinggu:'ture',
... sex:'m',
... age:500
... })
//修改數(shù)據(jù)
> db.xuyou.update({name:'wukong'}, {
... $set:{name:'dzsf'},
...$unset:{jinggu:1},
...$rename:{sex:'gender'},
...$inc:{age:16}
...})
===============result=============
{ "_id" : ObjectId("5ca737a79ff46db4a72f574a"), "name" : "wukong", "jinggu" : "ture", "sex" : "m", "age" : "500" }
{ "_id" : ObjectId("5ca756699ff46db4a72f574b"), "name" : "dzsf", "age" : 516, "gender" : "m" }
對(duì)于update而言,如果不加入匹配參數(shù),每次只能修改一行。故我們需要引進(jìn)新的參數(shù)。
- multi: 是指修改多行(即使查詢表達(dá)式命中多行,默認(rèn)也只改1行,如果想改多行,可以用此選項(xiàng))
> db.biao.update({gender:'n'}, {$set:{gender:'woman'}},{multi:1});
> db.biao.find()
{ "_id" : ObjectId("5ca75baee0fef6d9022eef1a"), "name" : "yhy", "gender" : "m" }
{ "_id" : ObjectId("5ca75baee0fef6d9022eef1b"), "name" : "syy", "gender" : "woman" }
{ "_id" : ObjectId("5ca75baee0fef6d9022eef1c"), "name" : "yhhhy", "gender" : "woman" }
- Upsert是指沒有匹配的行,則直接插入該行.(和mysql中的replace一樣)
db.biao.update({name:'yhhy'}, {$set:{name:'junshiwuyong'}}, {upsert:1});
> db.biao.update({name:'yjy'}, {$set:{name:'wusongdahu'},$setOnInsert:{gender:'man'}},{upsert:1});
============= result =================
{ "_id" : ObjectId("5ca779ec3eab4669f488b85c"), "name" : "junshiwuyong" }
{ "_id" : ObjectId("5ca77bd53eab4669f488b864"), "name" : "wusongdahu", "gender" : "man" }
2.4查操作(find)
db.stu.find() //查詢所有文檔 所有內(nèi)容
db.stu.find({},{gendre:1}) //查詢所有文檔,的gender屬性 (_id屬性默認(rèn)總是查出來)
db.stu.find({},{gender:1, _id:0}) //查詢所有文檔的gender屬性,且不查詢_id屬性
db.stu.find({gender:’male’},{name:1,_id:0}); //查詢所有g(shù)ender屬性值為male的文檔中的name屬性
3.MongoDB查詢表達(dá)式
3.1使用比較運(yùn)算符查詢
[圖片上傳失敗...(image-ea676-1554555623323)]
3.1.1主鍵為32的商品
> db.goods.find({goods_id:32})
3.1.2不屬于第三欄的所有商品($ne)
> db.goods.find({cat_id:{$ne:3}},{goods_id:1, cat_id:1,_id:0})
3.1.3價(jià)格高于3000的商品($gt)
> db.goods.find({shop_price:{$gt:3000}}, {goods_name:1,shop_price:1,_id:0})
3.1.4價(jià)格小于等于100的商品 ($lte)
> db.goods.find({shop_price:{$lte:100}},{goods_name:1,shop_price:1,_id:0})
3.1.5取出第4欄或者第11欄的商品($in)
db.goods.find({cat_id:{$in:[4,11]}},{goods_name:1,shop_price:1,_id:0,cat_id:1})
3.1.6篩選有共同項(xiàng)的成員信息($all)
> db.xuyou.find({hobby:{$all:['c']}})
3.2使用邏輯運(yùn)算符查詢

3.2.1價(jià)格在100-500之間的商品($and)
> db.goods.find({$and:[{shop_price:{$gte:100}} ,{shop_price:{$lte:500}}]}, {shop_price:1,goods_name:1,_id:0})
3.2.2取出不屬于第3欄且不屬于第11欄的商品(
nin, $nor)
//方法一:and
> db.goods.find({$and:[{cat_id:{$ne:3}}, {cat_id:{$ne:11}}]},{cat_id:1,goods_name:1,_id:0});
//方法二:nin
> db.goods.find({cat_id:{$nin:[3,11]}},{cat_id:1,goods_name:1,_id:0})
//方法三:nor
> db.goods.find({$nor:[{cat_id:3} ,{cat_id:11}]}, {cat_id:1,goods_name:1,_id:0})
3.3使用元素運(yùn)算符查詢

3.3.1取出goods_id以5為倍數(shù)的商品 ($mod)
> db.goods.find({goods_id:{$mod:[5,0]}},{goods_id:1,goods_name:1,_id:0})
3.3.2找出xuyou表中唯一存在age的信息($exists)
> db.xuyou.find({age:{$exists:1}})
3.3.3查詢age字段不同類型的信息($type)
//對(duì)于age來說,可以編寫成age:‘22’,同時(shí)也可以是是age:22
db.biao.find({age:{$type:1}}) //浮點(diǎn)型
db.biao.find({age:{$type:1}}) //字符串類型
3.4使用JS運(yùn)算符查詢
3.4.1條件查詢商品信息($where)
> db.goods.find({$where:'this.shop_price>5000'},{shop_price_id:1,goods_name:1,_id:0})
> db.goods.find({$where:'this.shop_price>200 && this.shop_price<500 || this.shop_price>300 && this.price<5000'}, {shop_price:1,goods_name:1,_id:0})
//&& 并且 ||或者
3.4.2條件查詢匹配商品開頭信息($regex)
db.goods.find({goods_name:{$regex:"諾基亞"}},{_id:0,goods_name:1})
4.MongoDB--游標(biāo)操作
4.1循環(huán)生成1000條數(shù)據(jù)
> for(var i=0; i<100000; i++) {
... db.data.insert({_id:i+1,title:'hello word',content:'aaa'+i});
... };
4.2游標(biāo)的使用
- 游標(biāo):通俗的說:游標(biāo)不是查詢結(jié)果,而是查詢的返回資源或者接口。通過這個(gè)接口,你可以逐條讀取數(shù)據(jù)。
4.2.1聲明游標(biāo)
> var mycusor = db.data.find({_id:{$lte:4}}) //定義游標(biāo)數(shù)量
> print(mycusor.next()) //第一次查詢,返回bson格式
[object BSON]
> printjson(mycusor.next()) //第二次查詢,游標(biāo)從2開始計(jì)數(shù)
{ "_id" : 2, "title" : "hello word", "content" : "aaa1" }
4.2.2判斷游標(biāo)是否到達(dá)盡頭
> printjson(mycusor.hasNext())
false
> var mycusor = db.data.find({_id:{$lte:4}})
> printjson(mycusor.hasNext())
true
4.2.3循環(huán)/(迭代)函數(shù)調(diào)用顯示游標(biāo)內(nèi)容
> var mycursor = db.data.find({_id:{$lte:5}})
//方式一:利用while循環(huán)實(shí)現(xiàn)
> while(mycursor.hasNext()) {
... printjson(mycursor.next());
... }
//方式二:利用for循環(huán)實(shí)現(xiàn)
> for(var mycursor=db.data.find({_id:{$lte:5}}) ; mycursor.hasNext();) {
... printjson(mycursor.next())
... }
//方式三:利用forEach函數(shù)實(shí)現(xiàn)
> mycusor.forEach(function(key){printjson(key)});
{ "_id" : 1, "title" : "hello word", "content" : "aaa0" }
{ "_id" : 2, "title" : "hello word", "content" : "aaa1" }
{ "_id" : 3, "title" : "hello word", "content" : "aaa2" }
{ "_id" : 4, "title" : "hello word", "content" : "aaa3" }
{ "_id" : 5, "title" : "hello word", "content" : "aaa4" }
> var mycusor = db.data.find({_id:{$lte:5}})
> mycusor.forEach(function(key){print('you id is '+key._id)});
you id is 1
you id is 2
you id is 3
you id is 4
you id is 5
4.2.4游標(biāo)在分頁中的應(yīng)用
比如查詢1000行(跳過100頁取10行),一般我們假設(shè)每頁有N行,當(dāng)前是page頁就需要跳過前(page-1)*N行,在MongoDB中使用skip()和limit()函數(shù)來實(shí)現(xiàn)
> var mycursor = db.data.find().skip(99995);
> mycursor.forEach(function(key) {printjson(key)});
{ "_id" : 99996, "title" : "hello word", "content" : "aaa99995" }
{ "_id" : 99997, "title" : "hello word", "content" : "aaa99996" }
{ "_id" : 99998, "title" : "hello word", "content" : "aaa99997" }
{ "_id" : 99999, "title" : "hello word", "content" : "aaa99998" }
{ "_id" : 100000, "title" : "hello word", "content" : "aaa99999" }
查詢第901頁,每頁10條
> var mycursor = db.data.find().skip(9985).limit(10)
> mycursor.forEach(function(key) {printjson(key)});
{ "_id" : 9986, "title" : "hello word", "content" : "aaa9985" }
{ "_id" : 9987, "title" : "hello word", "content" : "aaa9986" }
{ "_id" : 9988, "title" : "hello word", "content" : "aaa9987" }
{ "_id" : 9989, "title" : "hello word", "content" : "aaa9988" }
{ "_id" : 9990, "title" : "hello word", "content" : "aaa9989" }
{ "_id" : 9991, "title" : "hello word", "content" : "aaa9990" }
{ "_id" : 9992, "title" : "hello word", "content" : "aaa9991" }
{ "_id" : 9993, "title" : "hello word", "content" : "aaa9992" }
{ "_id" : 9994, "title" : "hello word", "content" : "aaa9993" }
{ "_id" : 9995, "title" : "hello word", "content" : "aaa9994" }
4.2.5 顯示數(shù)組 toArray的使用
- 不要隨意使用toArray()。因?yàn)椋捍撕瘮?shù)會(huì)把所有的行立即以對(duì)象的形式組織在內(nèi)存里??梢栽谌〕錾贁?shù)幾行時(shí)候用此功能。
> var mycursor = db.data.find().skip(99995).limit(5)
> mycursor.toArray();
[
{
"_id" : 99996,
"title" : "hello word",
"content" : "aaa99995"
},
{
"_id" : 99997,
"title" : "hello word",
"content" : "aaa99996"
},
{
"_id" : 99998,
"title" : "hello word",
"content" : "aaa99997"
},
{
"_id" : 99999,
"title" : "hello word",
"content" : "aaa99998"
},
{
"_id" : 100000,
"title" : "hello word",
"content" : "aaa99999"
}
]
//調(diào)取一行數(shù)據(jù)
> printjson(mycursor.toArray()[3])
{ "_id" : 99999, "title" : "hello word", "content" : "aaa99998" }
4.MongoDB--索引
- 索引提高查詢速度,降低讀入速度,權(quán)衡常用的字段查詢,不必在太多列上建立索引
- 在MongoBD中索引可以按字段升序/降序來創(chuàng)建,便于排序
- 默認(rèn)是用btree來組織索引文件,同時(shí)也允許建立hash索引
| 索引作用類型 | 索引性質(zhì) |
|---|---|
| 單列索引 | 唯一索引 |
| 多列索引 | 稀疏索引 |
| 子文檔索引 | 哈希索引 |
4.1創(chuàng)建一個(gè)MongoDB數(shù)據(jù)文件
> for(var i=1;i<=1000;i++) {
... db.stu.insert({sn:i,name:'student'+i})
... }
4.2索引作用類型
4.2.1創(chuàng)建/ 查詢/ 刪除單列索引
//創(chuàng)建索引的兩種方式
> db.stu.ensureIndex({name:-1}) //-1 倒序
> db.stu.createIndex({sn:1}) //1 正序
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
//查詢索引
> db.stu.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "dd.stu"
},
{
"v" : 2,
"key" : {
"sn" : 1
},
"name" : "sn_1",
"ns" : "dd.stu"
}
]
//刪除索引
> db.stu.dropIndex({name:-1}) //刪除單個(gè)索引
{ "nIndexesWas" : 3, "ok" : 1 }
> db.stu.dropIndexes() //刪除所有索引
{
"nIndexesWas" : 3,
"msg" : "non-_id indexes dropped for collection",
"ok" : 1
}
4.2.2添加多列索引
> db.stu.ensureIndex({sn:1,name:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
4.2.3 子文檔索引
> db.shop.insert({name:'Nokia',spc:{weight:120,area:'taiwan'}})
> db.shop.insert({name:'sanxing',spc:{weight:100,area:'hangzhou'}})
> db.shop.find({'spc.area':'taiwan'}) //查詢子文檔索引
{ "_id" : ObjectId("5ca9780c9d13524750104f1e"), "name" : "Nokia", "spc" : { "weight" : 120, "area" : "taiwan" } }
//創(chuàng)建子文檔索引
> db.shop.ensureIndex({'spc.area':1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
4.3索引性質(zhì)
4.3.1唯一索引
> db.stu.insert({email:'a@163.com'})
> db.stu.insert({email:'b@163.com'})
//創(chuàng)建唯一索引:如果加c@163.com有且只能加入一個(gè)
> db.stu.createIndex({email:1},{unique:true})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
4.3.2稀疏索引
稀疏索引的特點(diǎn):如果針對(duì)field做索引,對(duì)于不含filed列的文檔將不建立索引。與之相對(duì),普通索引:會(huì)把該文檔的field列的值認(rèn)為是null并建立索引
> db.stu.find()
{ "_id" : ObjectId("5cab2e2b1fa81e696a0cc1f7"), "email" : "a@163.com" }
{ "_id" : ObjectId("5cab2e321fa81e696a0cc1f8"), "email" : "b@163.com" }
{ "_id" : ObjectId("5cab2fa81fa81e696a0cc1f9"), "email" : "c@163.com" }
{ "_id" : ObjectId("5cab31021fa81e696a0cc1fc") }
> db.stu.ensureIndex({email:1},{sparse:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.tea.find({email:null})
4.3.3 哈希索引
> db.foo.insert([{title:'hello'},{title:'word'}])
> db.foo.ensureIndex({title:'hashed'})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
四、MongoBD數(shù)據(jù)庫管理
1.MongoBD用戶管理
1.1修改配置文件
在 /etc/mongo.conf中添加配置內(nèi)容
security:
# 啟用或禁用基于角色的訪問控制(RBAC)來控制每個(gè)用戶對(duì)數(shù)據(jù)庫資源和操作的訪問
# disabled | enabled
authorization: enabled //此行前必須有兩個(gè)空格
Mongo 安裝好后,默認(rèn)是 disabled 的,要想啟用認(rèn)證,必須先創(chuàng)建一個(gè)用戶管理員賬號(hào)。這個(gè)賬號(hào)專門用于創(chuàng)建用戶,包括給這些用戶賦予不同的角色,并且可以針對(duì)不同的數(shù)據(jù)庫賦予不同的角色。
1.2 創(chuàng)建用戶
1.2.1創(chuàng)建管理用戶
> use admin
> db.createUser(
... {
... user: "dba",
... pwd: "dba",
... roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
... }
... )
//退出重新認(rèn)證即可
[root@localhost ~]# mongo
> use admin
switched to db admin
> db.auth('dba','dba')
1
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
在創(chuàng)建用戶時(shí)最重要的就是權(quán)限的選擇問題
- user:用戶名
- pwd:密碼
- roles:指定用戶的角色,可以用一個(gè)空數(shù)組給新用戶設(shè)定空角色;在roles字段,可以指定內(nèi)置角色和用戶定義的角色。
? 1.數(shù)據(jù)庫用戶角色:read、readWrite;
- 數(shù)據(jù)庫管理角色:dbAdmin、dbOwner、userAdmin;
- 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
- 備份恢復(fù)角色:backup、restore;
- 所有數(shù)據(jù)庫角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
- 超級(jí)用戶角色:root
// 這里還有幾個(gè)角色間接或直接提供了系統(tǒng)超級(jí)用戶的訪問(dbOwner 、userAdmin、userAdminAnyDatabase)- 內(nèi)部角色:__system
其中的具體角色問題
Read:允許用戶讀取指定數(shù)據(jù)庫
readWrite:允許用戶讀寫指定數(shù)據(jù)庫
dbAdmin:允許用戶在指定數(shù)據(jù)庫中執(zhí)行管理函數(shù),如索引創(chuàng)建、刪除,查看統(tǒng)計(jì)或訪問system.profile
userAdmin:允許用戶向system.users集合寫入,可以找指定數(shù)據(jù)庫里創(chuàng)建、刪除和管理用戶
clusterAdmin:只在admin數(shù)據(jù)庫中可用,賦予用戶所有分片和復(fù)制集相關(guān)函數(shù)的管理權(quán)限。
readAnyDatabase:只在admin數(shù)據(jù)庫中可用,賦予用戶所有數(shù)據(jù)庫的讀權(quán)限
readWriteAnyDatabase:只在admin數(shù)據(jù)庫中可用,賦予用戶所有數(shù)據(jù)庫的讀寫權(quán)限
userAdminAnyDatabase:只在admin數(shù)據(jù)庫中可用,賦予用戶所有數(shù)據(jù)庫的userAdmin權(quán)限
dbAdminAnyDatabase:只在admin數(shù)據(jù)庫中可用,賦予用戶所有數(shù)據(jù)庫的dbAdmin權(quán)限。
root:只在admin數(shù)據(jù)庫中可用。超級(jí)賬號(hào),超級(jí)權(quán)限
1.2.2創(chuàng)建root超級(jí)用戶
> use admin
switched to db admin
> db.auth("dba","dba")
1
> db.createUser({
... user:"wudi",
... pwd:"1",
... roles:[{role:"root",db:"admin"}]
... })
> use admin
switched to db admin
> db.auth("wudi","1")
1
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
stu 0.000GB
> use stu
switched to db stu
> show tables
foo
1.2.3創(chuàng)建單數(shù)據(jù)庫讀寫用戶
> use stu
switched to db stu
> db.createUser({
... user:"yy",
... pwd:"1",
... roles:[{role:"readWrite",db:"stu"}]
... })
//退出數(shù)據(jù)庫后重新登錄
[root@localhost ~]# mongo
MongoDB shell version v3.6.12
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("7bb6702e-9398-4449-a9a8-279b95362845") }
MongoDB server version: 3.6.12
> use stu
switched to db stu
> db.auth('yy','1')
1
> show tables
> db.foo.insert({name:'effcf',age:19})
WriteResult({ "nInserted" : 1 })
> db.foo.insert({name:'rgfv',age:22})
WriteResult({ "nInserted" : 1 })
> db.foo.find()
{ "_id" : ObjectId("5c839f9d5cdcf23c553fe98a"), "name" : "effcf", "age" : 19 }
{ "_id" : ObjectId("5c839fa65cdcf23c553fe98b"), "name" : "rgfv", "age" : 22 }
1.2.4創(chuàng)建單數(shù)據(jù)庫只讀用戶
> use admin
switched to db admin
> db.auth('dba','dba')
1
> use stu
> db.createUser({
... user:"yt",
... pwd:"1",
... roles:[{role:"read",db:"stu"}]
... })
[root@localhost ~]# mongo
MongoDB shell version v3.6.12
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("a48cb5be-b7fa-453d-92e7-6cf8cabc98c3") }
MongoDB server version: 3.6.12
> use stu
switched to db stu
> db.auth("yt","1")
1
> show tables
foo
> db.foo.find()
{ "_id" : ObjectId("5c839f9d5cdcf23c553fe98a"), "name" : "effcf", "age" : 19 }
{ "_id" : ObjectId("5c839fa65cdcf23c553fe98b"), "name" : "rgfv", "age" : 22 }
> db.foo.insert({name:'dd',age:88})
WriteResult({
"writeError" : {
"code" : 13,
"errmsg" : "not authorized on stu to execute command { insert: \"foo\", ordered: true, lsid: { id: UUID(\"a48cb5be-b7fa-453d-92e7-6cf8cabc98c3\") }, $db: \"stu\" }"
}
})
1.3管理用戶
> use admin
switched to db admin
> db.auth('dba','dba')
1
> db.system.users.find().pretty()
{
"_id" : "admin.dba",
"user" : "dba",
"db" : "admin",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "KEmJdox7dvQzfUGRWuTVXQ==",
"storedKey" : "ONHWxuh4wU1RZFR8Al/oX6Z1VWw=",
"serverKey" : "Pw8n1yYG71zihd+5MyZ4JWYR+Yg="
}
},
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
{
"_id" : "stu.yy",
"user" : "yy",
"db" : "stu",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "W0Di3xc3oehmnIyg4Sm7JA==",
"storedKey" : "9NovDOeoMUdY5d6UW8a8Jm7iKW0=",
"serverKey" : "8bAt6hWPHMa2FPbnsoRiBFUdKSI="
}
},
"roles" : [
{
"role" : "readWrite",
"db" : "stu"
}
]
}
{
"_id" : "stu.yt",
"user" : "yt",
"db" : "stu",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "Js4z7J4b+vRPvzYRGYqEOg==",
"storedKey" : "/vpk/EuyBfMCiKqDWoqZvOCKprU=",
"serverKey" : "Z7riO2r2MBQXvvJbBAxWW6mxbjs="
}
},
"roles" : [
{
"role" : "read",
"db" : "stu"
}
]
}
{
"_id" : "admin.wudi",
"user" : "wudi",
"db" : "admin",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "yexzX4oxSWEoynisD7MDFg==",
"storedKey" : "RgZGju6pUtX1ompTS7b9sXpMM6M=",
"serverKey" : "bbLRcO61HTl2j/l+5ZVqjHXoT4A="
}
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
2. MongoD數(shù)據(jù)庫的備份與還原
2.1 MongoDB數(shù)據(jù)導(dǎo)出(mongoexport)
-
mongoexport遭遇Authentication failed:
需要添加 --authenticationDatabase=admin ,即可導(dǎo)出成功
查詢工具的各個(gè)參數(shù)
general options:
--help print usage
--version print the tool version and exitverbosity options:
-v, --verbose more detailed log output (include multiple times for
more verbosity, e.g. -vvvvv)
--quiet hide all log outputconnection options:
-h, --host= mongodb host to connect to (setname/host1,host2 for
replica sets)
--port= server port (can also use --host hostname:port)ssl options:
--ssl connect to a mongod or mongos that has ssl enabled
--sslCAFile= the .pem file containing the root certificate chain from
the certificate authority
--sslPEMKeyFile= the .pem file containing the certificate and key
--sslPEMKeyPassword= the password to decrypt the sslPEMKeyFile, if necessary
--sslCRLFile= the .pem file containing the certificate revocation list
--sslAllowInvalidCertificates bypass the validation for server certificates
--sslAllowInvalidHostnames bypass the validation for server name
--sslFIPSMode use FIPS mode of the installed openssl libraryauthentication options:
-u, --username= username for authentication
-p, --password= password for authentication
--authenticationDatabase= database that holds the user's credentials
--authenticationMechanism= authentication mechanism to usenamespace options:
-d, --db= database to use
-c, --collection= collection to useoutput options:
-f, --fields= comma separated list of field names (required for
exporting CSV) e.g. -f "name,age"
--fieldFile= file with field names - 1 per line
--type= the output format, either json or csv (defaults to
'json')
-o, --out= output file; if not specified, stdout is used
--jsonArray output to a JSON array rather than one object per line
--pretty output JSON formatted to be human-readablequerying options:
-q, --query= query filter, as a JSON string, e.g., '{x:{snapshot)
--skip= number of documents to skip
--limit= limit the number of documents to export--sort= sort order, as a JSON string, e.g. '{x:1}'
//導(dǎo)出全部數(shù)據(jù)
[root@localhost tmp]# mongoexport -u wudi -p 1 -d stu -c foo -o /tmp/sky.stu.json --authenticationDatabase=admin
2019-03-09T23:54:16.480+0800 connected to: localhost
2019-03-09T23:54:16.480+0800 exported 2 records
//導(dǎo)出數(shù)據(jù)中選定內(nèi)容
[root@localhost tmp]# mongoexport -u wudi -p 1 -d biao -c stu -f "sn,name" -q '{sn:{$lte:1000}}' -o /tmp/test.ss.json --authenticationDatabase=admin
2019-03-09T23:43:54.067+0800 connected to: localhost
2019-03-09T23:43:54.121+0800 exported 1000 records
//導(dǎo)出CSV格式數(shù)據(jù)內(nèi)容(CSV格式便于和傳統(tǒng)數(shù)據(jù)庫交換數(shù)據(jù))
[root@localhost tmp]# mongoexport -u wudi -p 1 -d biao -c stu -f "sn,name" -q '{sn:{$lte:1000}}' --csv -o /tmp/test.ss.csv --authenticationDatabase=admin
2019-04-12T11:07:26.420+0800 csv flag is deprecated; please use --type=csv instead
2019-04-12T11:07:26.425+0800 connected to: localhost
2019-04-12T11:07:26.462+0800 exported 1000 records
2.2 MongoDB數(shù)據(jù)導(dǎo)入(mongoimport)
//導(dǎo)入json格式數(shù)據(jù)
[root@localhost tmp]# mongoimport -u wudi -p 1 -d people -c age --type json --file /tmp/test.ss.json --authenticationDatabase=admin
2019-04-12T11:26:25.030+0800 connected to: localhost
2019-04-12T11:26:25.279+0800 imported 1000 documents
//導(dǎo)入csv格式數(shù)據(jù)(1)
[root@localhost tmp]# mongoimport -u wudi -p 1 -d people -c name --type csv -f "sn,name" --file /tmp/te.ceshi.csv --authenticationDatabase=admin
2019-04-12T11:33:24.289+0800 connected to: localhost
2019-04-12T11:33:24.329+0800 imported 11 documents
經(jīng)過觀察看出導(dǎo)入時(shí)將標(biāo)題修改為第一行數(shù)據(jù)
> db.auth("wudi","1")
1
> use people
switched to db people
> db.name.find()
{ "_id" : ObjectId("5cb0070422a89db7a5941f4c"), "sn" : "sn", "name" : "name" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f4d"), "sn" : 1, "name" : "student1" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f4e"), "sn" : 2, "name" : "student2" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f4f"), "sn" : 3, "name" : "student3" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f50"), "sn" : 5, "name" : "student5" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f51"), "sn" : 6, "name" : "student6" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f52"), "sn" : 7, "name" : "student7" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f53"), "sn" : 8, "name" : "student8" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f54"), "sn" : 4, "name" : "student4" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f55"), "sn" : 10, "name" : "student10" }
{ "_id" : ObjectId("5cb0070422a89db7a5941f56"), "sn" : 9, "name" : "student9" }
//導(dǎo)入CSV數(shù)據(jù)格式(2)
[root@localhost tmp]# mongoimport -u wudi -p 1 -d people -c hobby --headerline --type csv --file /tmp/te.ceshi.csv --authenticationDatabase=admin
2019-04-12T14:20:08.711+0800 connected to: localhost
2019-04-12T14:20:08.743+0800 imported 10 documents
2.3 MongoDB數(shù)據(jù)導(dǎo)入(mongodump)
mongodump 導(dǎo)出二進(jìn)制bson結(jié)構(gòu)的數(shù)據(jù)及其索引信息。
規(guī)律:
導(dǎo)出的文件放在database命名的目錄文件下
每個(gè)表導(dǎo)出2個(gè)文件,分別是bson結(jié)構(gòu)的數(shù)據(jù)文件,json的索引信息
如果不聲明表名。導(dǎo)出所有表信息
//導(dǎo)出坤庫內(nèi)全部信息
[root@localhost dump]# mongodump -u wudi -p 1 -d people --authenticationDatabase=admin
2019-04-12T14:34:36.805+0800 writing people.age to
2019-04-12T14:34:36.805+0800 writing people.name to
2019-04-12T14:34:36.805+0800 writing people.hobby to
2019-04-12T14:34:36.807+0800 done dumping people.name (11 documents)
2019-04-12T14:34:36.810+0800 done dumping people.age (1000 documents)
2019-04-12T14:34:36.815+0800 done dumping people.hobby (10 documents)
//導(dǎo)出指定表信息
[root@localhost dump]# mongodump -u wudi -p 1 -d people -c age --authenticationDatabase=admin
2.4 MongoDB數(shù)據(jù)導(dǎo)出(mongorestore)
[root@localhost people]# mongorestore -u wudi -p 1 --authenticationDatabase=admin -d people /tmp/dump/dump/people
2019-04-12T14:48:25.223+0800 the --db and --collection args should only be used when restoring from a BSON file. Other uses are deprecated and will not exist in the future; use --nsInclude instead
2019-04-12T14:48:25.223+0800 building a list of collections to restore from /tmp/dump/dump/people dir
2019-04-12T14:48:25.224+0800 reading metadata for people.age from /tmp/dump/dump/people/age.metadata.json
2019-04-12T14:48:25.430+0800 restoring people.age from /tmp/dump/dump/people/age.bson
2019-04-12T14:48:25.484+0800 reading metadata for people.name from /tmp/dump/dump/people/name.metadata.json
2019-04-12T14:48:25.484+0800 reading metadata for people.hobby from /tmp/dump/dump/people/hobby.metadata.json
2019-04-12T14:48:25.504+0800 restoring people.name from /tmp/dump/dump/people/name.bson
2019-04-12T14:48:25.530+0800 no indexes to restore
2019-04-12T14:48:25.530+0800 finished restoring people.name (11 documents)
2019-04-12T14:48:25.530+0800 restoring people.hobby from /tmp/dump/dump/people/hobby.bson
2019-04-12T14:48:25.559+0800 no indexes to restore
2019-04-12T14:48:25.559+0800 finished restoring people.age (1000 documents)
2019-04-12T14:48:25.578+0800 no indexes to restore
2019-04-12T14:48:25.578+0800 finished restoring people.hobby (10 documents)
2019-04-12T14:48:25.578+0800 done
[root@localhost people]# mongo
MongoDB shell version v3.6.12
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("177a96e5-5bc4-43ce-be78-9a924d5ae568") }
MongoDB server version: 3.6.12
> use admin
switched to db admin
> db.auth("wudi","1")
1
> use people
switched to db people
> show tables
age
hobby
name
3. MongoDB數(shù)據(jù)庫 - 復(fù)制集(replication )
含義:多臺(tái)服務(wù)器維護(hù)相同的數(shù)據(jù)副本,提高服務(wù)器的可用性。