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("索引名")


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM