mongodb 的 安裝配置,庫的備份恢復,基礎命令,聚合的用法和實例 ...
算是學習下來精煉的筆記,希望對大家有幫助。如果有問題歡迎大家指正。
0.概述
MongoDB 是由C++語言編寫的,是一個基於分散式文件存儲的開源資料庫系統。
在高負載的情況下,添加更多的節點,可以保證伺服器性能。
MongoDB 旨在為WEB應用提供可擴展的高性能數據存儲解決方案。
MongoDB 將數據存儲為一個文檔,數據結構由鍵值(key=>value)對組成。MongoDB 文檔類似於 JSON 對象。欄位值可以包含其他文檔,數組及文檔數組。
下麵是與sql概念的對比。能夠幫助我們更好的理解mongodb。
SQL術語/概念 | MongoDB術語/概念 | 解釋/說明 |
---|---|---|
database | database | 資料庫 |
table | collection | 資料庫表/集合 |
row | document | 數據記錄行/文檔 |
column | field | 數據欄位/域 |
index | index | 索引 |
table joins | 表連接,MongoDB不支持 | |
primary key | primary key | 主鍵,MongoDB自動將_id欄位設置為主鍵 |
總結下來,傳統的關係型資料庫的內容結構是
- 資料庫
- 表
- 行
- 欄位
Mongodb與之對應的就是
- 資料庫
- 集合
- 文檔
- 域
1.brew安裝
不推薦用brew,因為現在mongodb閉源了,brew里已經搜索不到mongodb,不過還是可以用brew安裝的,這篇就不寫了。
2.官網下載
直接去官網下載一個zip,解壓完放到usr/local/里(control+shift+。可以顯示隱藏文件夾),改名為mongodb。
然後添加一個環境變數就可以用了
$ export PATH=/usr/local/mongodb/bin:$PATH
這樣就添加好了,反正就是現在可以用了。
可以用mongo來測試是否安裝好了,如果都弄好了應該會彈出版本。
3.創建data/db文件夾
接下來就是新建data/db然後運行mongodb的步驟了。
不過mac os catalina現在有問題,跟目錄不讓寫東西了,所以要曲線救國,根據mongodb給的最新的解決辦法就是在/Users/(你的用戶名)/data/db/
里當目錄了
最後帶上--dbpath= ,如果不添加會預設到/data/db里
sudo mongod --dbpath=/Users/Wangzirui/data/db
如果不是卡特琳娜那好說,
sudo mkdir -p /data/db
然後 sudo mongod
就完事了。
更改catelina限制之後(關閉sip)。可以直接用 sudo mount -uw / 更改跟目錄許可權,就可以直接sudo mongod就完事了。
然後另一個終端進入/usr/loacl/mongodb/bin/
然後./mongo就啟動了mongo的客戶端
或者直接mongo也可以。
4.開啟服務創建客戶端
啟動服務:
sudo mount -uw /
sudo mongod
啟動客戶端:
mongo
5.命令
5.1 db操作
- 顯示資料庫
- show dbs
- 切換資料庫,沒有就新建一個
- use admin
- 顯示你在哪個資料庫里
- Db
- 刪除當前你use的那個資料庫
- db.dropDatebase()
- 新建資料庫
- use 資料庫名字
- 建完了show dbs不會立刻顯示,因為剛纔新建的資料庫裡面沒有數據。所以顯示不出來。
5.2 collection操作
- 顯示這個資料庫中有什麼集合
- show collections
- 新建集合,在use 一個資料庫的情況下
- db.createCollections(name,options)
- 然後show dbs現在可以看到use的資料庫了
- 刪除集合 ,在現在這個Use的資料庫的情況下
- db.你想要的collectionname.drop()
- 然後就刪掉了
5.3 document操作
collectionname代指相對應的collcetion名字(mysql里叫表,Mongodb里叫collection,都是一個資料庫里的一種結構) 現在操作的不是表也不是集合,而是集合里的一個數據結構叫做document,文檔,文檔相當於mysql里的一個記錄行。
- 往collection裡加數據,直接新建document
- db.collectionname.insert({"name":"wangzirui"})
- 增加多條要在insert的多個對象的外面加一個中括弧,表示這是一個對象數組。
- db.collectionname.insert([{name:"wangzirui"},{name:"laoli"}])
- 查看collection里的數據
- db.collectionname.find()
- Save,在_id一樣的情況下可以不報錯,然後直接覆蓋掉剛纔重覆Id的內容。
- db.collectionsname.save({_id:1001,name:"laowang",age:22})
- 更新document數據
- db.collectionname.update({當前數據},{替換數據},{配置項})
- db.collectionname.update({name:"laotie"},{name:"ergou"})
- 這樣會刪除其他內容,只存在一個name :ergou 所以要加$set保留其他的參數
- db.collectionname.update({name:"laotie"},{$set:{name:"ergou"}})
- 配置項裡加{Multi:true}加一個這個的話可以讓多個name:"laotie"一起改
- db.collectionname.update({name:"laotie"},{$set:{name:"ergou"}},{multi:true})
- 刪除document內容,如果不加第二個參數,預設是把集合里的符合第一條的都刪掉。
- Db.collectionname.remove({name:"laotie"},{justOne:true})
5.4 document 查詢
經過上面的講述,能瞭解到一點,基於database來查詢collections里的數據都是通過db.collcetion_name.方法 來進行操作的,同理。對document的查詢,我們之前也在查看collection時用過,他就是find()方法。
find裡面可以加參數,不加的話就是現實collection里所有的document。
- find()方法里可以加條件,例如db.collectionname.find({age:18})
- 如果一行一行的話不好看,可以再db.collectionname.find({age:18})後面加.pretty()
- 比較運算符
- less than 小於 $lt db.collection_name.find(age:{$lt:18})
- less than equal 小於等於 $lte
- Geater than 大於 $gt
- $gte 大於等於
- $ne 不等於
- 取範圍內的 $in
- $in:[10,20,30]
- db.collection_name.find({age:{$in:[10,20,30]}})
- 並操作
- db.collection_name.find(age:18,name:"laotie")
- 或操作
- db.collection_name.find({$or:[{age:18},{name:"laotie"}]}
- 正則
- db.collection_name.find({age:/^1/})或者db.collection_name.find({age:$regex:"^1"})
- 限制和跳過,一般用於分頁
- limit(2)
- skip(2)
投影
- 比如說find({這裡放具體參數},{這裡放投影})
- db.collection_name.find({age:{$lt:18}},{_id:0,age:1}) 這樣只會顯示每個對象裡面只有一個age選項了
- 註意,如果投影里不加_id的選項的話 ,預設是自動顯示的。只能給_id設置 0。如果別的欄位不想讓他顯示直接不在裡面加。其他的想要顯示的話直接把屬性加進去就行了。
通過Js函數來篩選數據
$where:
db.collection_name.find({$where:function(){
Return age>10}})
根據某個欄位排序
- sort
- db.collection_name.find().sort({age:1}) 如果降序的話要帶-1
計數
count()
直接在查詢出來的後面加上就可以顯示了
db.collection_name.find({$where:function(){
Return age>10}}).count()
去重
- db.student.distinct("name",{"age" : 18})
- 這樣可以直接把name一樣還有age為18的都給去重
6.備份和恢復
6.1備份
直接在終端輸入,不要在mongodb的客戶端輸入
mongodump -h hostname -d dbname -o dbdirectory
-h 伺服器地址,可以指定埠號。本機可以不填
-d 具體Mongodb下哪個資料庫
-o 你想保存到本地的什麼地方
例如本機 下在termainal直接輸入 mongodump -d laotie -o wenjianjia
然後就把 laotie這個資料庫保存到Users/wangzirui/wenjianjia這個文件夾里了
6.2恢復
同樣直接在終端輸入
Mongorestore -h hostname -d dbname --dir
-h 伺服器地址,可以指定埠號。本機可以不填
-d 你想讓這個資料庫叫什麼,不一定是原名
-Dir 這個備份文件在哪裡
7.聚合
aggregate,就是一個管道,類似中間件或者是函數的鏈式調用。最終導出想要的數據。
7.1group
首先放一個student集合的數據,聚合所有的操作都是按照這些數據來的。
> db.student.find()
{ "_id" : ObjectId("5e003b92f197cb08dc74a311"), "name" : "duanyuxin", "age" : 21, "sex" : "male" }
{ "_id" : ObjectId("5e003b92f197cb08dc74a312"), "name" : "baiyu", "age" : 20, "sex" : "male" }
{ "_id" : ObjectId("5e003f66f197cb08dc74a313"), "name" : "wangzirui", "age" : 22, "sex" : "male" }
{ "_id" : ObjectId("5e003f8ff197cb08dc74a314"), "name" : "zhuhuan", "age" : 22, "sex" : "female" }
{ "_id" : ObjectId("5e003f8ff197cb08dc74a315"), "name" : "caoyajing", "age" : 12, "sex" : "female" }
先放例子:
> db.student.aggregate({
$group:{_id:"$sex",avg_age:{$avg:"$age"}}
})
{ "_id" : "male", "avg_age" : 21 }
{ "_id" : "female", "avg_age" : 17 }
在$group
的對象里,前面開頭的域(欄位)代表下麵將要輸出的域的值。 後面的$sex
表示的是我拿什麼東西當做group分組的鍵值。如果我針對不同的age分組,那麼我將會得到
> db.student.aggregate({
$group:{_id:"$age"}
})
{ "_id" : "12"}
{ "_id" : "20"}
{ "_id" : "21"}
{ "_id" : "22"}
的結果。
接著說avg_age,這個域是我們自己定義的。(可能是先入為主,我總覺得說欄位更為適應,大家也更容易理解),叫什麼都行,但是後面$avg:"$age"
的意思就是,首先前面$avg
就是取平均值,取得就是你後面$age
的平均值。然後輸出的時候就列印"avg_age:前面符合id分類的文檔的age平均值"
如果想計算整個文檔的某些值,僅需要把_id:null
然就可以不分組,直接用整個文檔來算。
> db.student.aggregate({
$group:{_id:null,avg_age:{$avg:"$age"}}
})
{ "_id" : null, "avg_age" : 19.4 }
$sum:
另外講一個$sum的用法,先看怎麼用。
> db.student.aggregate({
$group:{_id:null,count:{$sum:1},avg_age:{$avg:"$age"}}
})
{ "_id" : null, "count" : 5, "avg_age" : 19.4 }
在剛纔的基礎上加了一個$sum:1
里 $sum
顧名思義是求和用的,後面是求和的倍數,如果你設成2的話結果就乘2變成10.一般用來計數的話普遍還是設置成1的。
利用$group去重:
$group
不止可以添加一個分組條件,也可以添加多個分組條件,如果把每個條件都對應文檔的域,那麼就相當於去重操作。
> db.student.aggregate({
$group:{_id:{name:"$name",sex:"$sex",age:"$age"}}
})
然後接下來用別的通道來進行下一步的操作就可以了。但是接下來的操作要用到的屬性就是$_id.name
類似的。因為我們去重時把屬性都給了叫_id的域。
7.2$project
重構輸出結構,也就是在aggregete的通道特性,然在最後調整你想要的輸出結構。大體上和投影類似。
放慄子:
> db.student.aggregate(
{
$group:{_id:null,count:{$sum:1},avg_age:{$avg:"$age"}}
},
{
$project:{sex:"$_id",count:"$count",avg_age:"$avg_age"}
}
)
{ "_id" : null, "sex" : null, "count" : 5, "avg_age" : 19.4 }
同理,可以用1 或者0代替。具體不舉例子了,沒什麼大用。
7.4 $match
聽名字就知道是過濾用的,雖然find同樣可以過濾,但是不能將find出來的結果傳給下一個管道。
比如說你想呀知道年齡大於20的男生和女生分別有幾個人
可以按照下麵的方式操作
db.student.aggregate(
{$match:{age:{$gt:19}}},
{$group:{_id:"$sex",count:{$sum:1}}},
{$project:{_id:0,sex:"$_id",count:1}}
)
{ "count" : 3, "sex" : "male" }
{ "count" : 1, "sex" : "female" }
大體就是這樣,裡面填的東西和find里是差不多的。
7.5 $sort
用法跟普通的用法一致,直接放慄子:
db.student.aggregate(
{$group:{_id:"$sex",count:{$sum:1}}},
{$sort:{age:1}}
)
{ "_id" : "female", "count" : 2 }
{ "_id" : "male", "count" : 3 }
如果前面的其他方法都看懂了,這個應該不成問題。就不解釋了。
7.6 $limit,skip
同樣跟前面很像,直接放例子:
db.student.aggregate(
{$skip:2},{$limit:2}
)
{ "_id" : ObjectId("5e003f66f197cb08dc74a313"), "name" : "wangzirui", "age" : 22, "sex" : "male" }
{ "_id" : ObjectId("5e003f8ff197cb08dc74a314"), "name" : "zhuhuan", "age" : 22, "sex" : "female" }
不解釋了。
8.創建索引
for(i=0;i<100000;i++){db.test.insert({name:'test'+i,age:i})}
在數據量特別龐大的時候,尋找數據就會變得慢一點。
所以要針對性的給集合建立索引
db.test.ensureIndex({name:1})
然後這個集合就有兩個索引了,之前那個索引叫_id,現在添加了一個域name也作為索引。
關於索引的幾個操作:
- 創建唯一索引
- db.test.ensureIndex({name:1},{uniqe:true})
- 建立聯合索引
- db.test.ensureIndex({name:1},{age:1})
- 查看當前集合的索引
- db.test.getIndexes()
- 刪除索引
- db.t1.dropIndex("索引名")