官網:https://www.mongodb.com/javascript
MongoDB 是一個基於分佈式文件存儲的數據庫,由 C++ 語言編寫,旨在爲 WEB 應用提供可擴展的高性能數據存儲解決方案。html
MongoDB 是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。前端
07/05/2017 Current Stable Release (3.4.6)java
https://www.mongodb.com/download-center#communitynode
MongoDB 將數據目錄存儲在 db 目錄下,需手動建立。angularjs
1
|
E:
\MongoDB
\data
\db
|
爲了從命令提示符下運行MongoDB服務器,你必須從MongoDB\bin
目錄中執行mongod.exe
文件,不要關閉服務。ctrl + c
關閉。web
1
|
mongod.exe --dbpath E:
\MongoDB
\data
\db
|
運行 mongo.exesql
MongoDB Shell是MongoDB自帶的交互式Javascript shell,用來對MongoDB進行操做和管理的交互式環境。mongodb
添加系統環境 path E:\MongoDB\Server\3.4\bin
shell
檢測:cmd 中輸入 mongod --help
新建文件:E:\MongoDB\logs\logs.log
將 MongoDB 服務器做爲 Windows 服務隨 Windows 啓動而開啓:
1
|
mongod.exe
--logpath
"E:\MongoDB\logs\logs.log"
--logappend
--dbpath
"E:\MongoDB\data"
--directoryperdb
--serviceName MongoDB
--install
|
開啓 MongoDB 服務:net start MongoDB
中止 MongoDB 服務:net stop MongoDB
刪除 MongoDB 服務:sc delete MongoDB
接下來就能夠在 cmd 中運行 E:\MongoDB\Server\3.4\bin
裏面的 *.exe
程序了
mongo
mongorestore
mongodump
監控
GUI
多個集合邏輯上組織在一塊兒,就是數據庫。
數據庫命名規範:
有一些數據庫名是保留的,能夠直接訪問這些有特殊做用的數據庫。
多個文檔組成一個集合,至關於關係數據庫的表。
全部存儲在集合中的數據都是 BSON 格式,BSON 是類 JSON 的一種二進制形式的存儲格式,簡稱 Binary JSON。
集合名命名規範:
MongoDB 將數據存儲爲一個文檔,數據結構由鍵值對組成。
MongoDB 文檔是一組鍵值對(即BSON,二進制的 JSON),相似於 JSON 對象。字段值能夠包含其餘文檔,數組及文檔數組。
文檔鍵命名規範:
須要注意的是:
ObjectId:主鍵,一種特殊並且很是重要的類型,每一個文檔都會默認配置這個屬性,屬性名爲_id,除非本身定義,方可覆蓋
1
|
db
|
沒有數據的數據庫不予顯示
MongoDB 中默認的數據庫爲 test,若是你沒有建立新的數據庫,集合將存放在 test 數據庫中。
1
|
show dbs
|
若是數據庫不存在,則建立數據庫,不然切換到指定數據庫。
1
|
use
db_name
|
1
|
db
.serverStatus()
|
1
|
db
.stats()
|
1
|
db
.dropDatabase()
|
1
2
3
|
show
tables
或
show collections
|
刪除裏面的文檔,但集合還在
1
|
db
.col_name
.remove({})
|
刪除集合
1
|
db
.col_name
.drop()
|
查看集合詳細信息
MongoDB 的3.0後的版本分了三種模式 queryPlanner、executionStats、allPlansExecution
1
|
db
.col_name
.find({
key:value})
.explain("
allPlansExecution")
|
MongoDB 使用 insert() 或 save() 方法向集合中插入文檔:
若是該集合不在該數據庫中, MongoDB 會自動建立該集合並插入文檔。
insert() 或 save() 方法均可以向collection裏插入數據,二者區別:
1
2
3
|
db
.col_name
.insert(document)
db
.col_name
.save(document)
|
插入一個文檔到 col 集合中:
1
2
3
4
5
6
7
8
|
db
.col_1
.insert({
title:
'MongoDB 教程',
description:
'MongoDB 是一個 Nosql 數據庫',
by:
'菜鳥教程',
url:
'http://www.runoob.com',
tags: [
'mongodb',
'database',
'NoSQL'],
likes:
100
})
|
也能夠將文檔數據定義爲一個變量,以下所示:
1
2
3
4
5
6
7
8
9
10
|
document = ({
title:
'MongoDB 教程',
description:
'MongoDB 是一個 Nosql 數據庫',
by:
'菜鳥教程',
url:
'http://www.runoob.com',
tags: [
'mongodb',
'database',
'NoSQL'],
likes:
100
});
db.col_2.insert(
document)
|
remove() 函數是用來刪除集合中的數據
在執行 remove() 函數前先執行 find() 命令來判斷執行的條件是否正確,這是一個比較好的習慣。
1
2
3
4
5
6
7
8
9
10
11
|
db
.col_name
.remove(
<
query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
-
query :(可選)刪除的文檔的條件。
-
justOne : (可選)若是設爲
true 或 1,則只刪除一個文檔。
-
writeConcern :(可選)拋出異常的級別。
|
刪除集合中全部文檔
1
|
db
.col
.remove({})
|
移除 col_1 集合中 title 爲 MongoDB save 的文檔,只刪除第一條找到的記錄
1
|
db
.col_1
.remove({
'title':
'MongoDB save'},
1)
|
MongoDB 使用 update() 和 save() 方法來更新集合中的文檔
update() 方法用於更新已存在的文檔
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
db.col_name.update(
<query>,
<
update>,
{
upsert: <
boolean>,
multi: <
boolean>,
writeConcern: <document>
}
)
- query :
update 的查詢條件,相似sql
update查詢內
where後面的。
-
update :
update的對象和一些更新的操做符(如$,$inc...)等,也能夠理解爲sql
update查詢內
set後面的
-
upsert : 可選,這個參數的意思是,若是不存在
update 的記錄,是否插入記錄,
true 爲插入,默認是
false,不插入。
- multi : 可選,mongodb 默認是
false,只更新找到的第一條記錄,若是這個參數爲
true,就把按條件查出來多條記錄所有更新。
- writeConcern :可選,拋出異常的級別。
|
經過 update() 方法來更新 col_1 集合中的 title
$set 操做符爲部分更新操做符,只更新 $set 以後的數據,而不是覆蓋以前的數據
1
|
db.col_1.
update({
'title':
'MongoDB 教程' }, { $set: {
'title':
'MongoDB' } })
|
以上語句只會修改第一條發現的文檔,若是要修改多條相同的文檔,則須要設置 multi 參數爲 true。
1
|
db.col_1.
update({
'title':
'MongoDB 教程' }, { $set: {
'title':
'MongoDB' } }, { multi: true })
|
save() 方法經過傳入的文檔來替換已有文檔。語法格式以下:
1
2
3
4
5
6
|
db
.col_name
.save(
<
document>,
{
writeConcern: <document>
}
)
|
如下實例中咱們替換了 col_1 的文檔數據:
1
2
3
4
5
6
7
8
9
10
|
document = ({
"_id":
"1",
"title":
"MongoDB save",
"description":
"MongoDB 是一個 Nosql 數據庫",
"by":
"菜鳥",
"url":
"http://www.runoob.com",
"tags": [
"mongodb",
"database",
"NoSQL"],
});
db.col_1.save(
document)
|
find() 方法,它返回集合中全部文檔。
findOne() 方法,它只返回一個文檔。
1
2
3
4
|
db.col_name.find(query, projection)
-
query :可選,使用查詢操做符指定查詢條件
-
projection :可選,使用投影操做符指定返回的鍵。查詢時返回文檔中全部鍵值, 只需省略該參數便可(默認省略)。
|
格式化輸出:
1
|
db
.col_name
.find()
.pretty()
|
查看集合中文檔的個數:
1
|
db
.col_name
.find()
.count()
|
跳過指定數量的數據:
1
|
db
.col_name
.find()
.skip()
|
讀取指定記錄的條數:
1
|
db
.col_name
.find()
.limit()
|
排序:
sort()方法能夠經過參數指定排序的字段,並使用 1 和 -1 來指定排序的方式,其中 1 爲升序排列,而-1是用於降序排列。
1
|
db
.col_name
.find()
.sort({
key:
1})
|
sort()方法能夠經過參數指定排序的字段,並使用 1 和 -1 來指定排序的方式,其中 1 爲升序排列,而-1是用於降序排列。
若是你想獲取」col」集合中 「likes」 大於100,小於 200 的數據,你可使用如下命令:
1
2
3
4
|
db.col.find({likes : {
$
lt :
200,
$
gt :
100}})
// 相似於SQL語句:
Select * from col where likes>
100
AND likes<
200;
|
條件操做符 | 中文 | 全英文 |
---|---|---|
$gt | 大於 | greater than |
$gte | 大於等於 | greater than equal |
$lt | 小於 | less than |
$lte | 小於等於 | less than equal |
$ne | 不等於 | not equal |
用來檢索集合中匹配的數據類型
若是想獲取 「col」 集合中 title 爲 String 的數據,你可使用如下命令:
1
|
db
.col
.find({
"title" : {
$type :
2}})
|
find() 方法能夠傳入多個鍵(key),每一個鍵(key)以逗號隔開,語法格式以下:
1
2
3
4
|
db.col_name.find(
{key1:value1, key2:value2}).pretty()
// 相似於 SQL and 語句:
SELECT *
FROM col_name
WHERE key1=
'value1'
AND key2=value2
|
1
2
3
4
|
db.col_name.
find({ $
or: [{
"by":
"菜鳥教程" }, {
"title":
"MongoDB 教程" }] }).pretty()
// 相似於 SQL or 語句:
SELECT *
FROM col_name WHERE key1=value1
OR key2=value2
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
db.col_name.find({
"likes": {
$gt:
50
},
$or: [{
"by":
"菜鳥教程"
}, {
"title":
"MongoDB 教程"
}]
}).pretty()
// 相似常規 SQL 語句:
SELECT * FROM col_name
where likes>
50 AND (
by =
'菜鳥教程' OR title =
'MongoDB 教程')
|
注意:從 mongoDB 3.0 開始,ensureIndex 被廢棄,從此都僅僅是 createIndex 的一個別名。
索引一般可以極大的==提升查詢的效率==,若是沒有索引,MongoDB在讀取數據時必須掃描集合中的每一個文件並選取那些符合查詢條件的記錄。
這種掃描全集合的查詢效率是很是低的,特別在處理大量的數據時,查詢能夠要花費幾十秒甚至幾分鐘,這對網站的性能是很是致命的。
索引是特殊的數據結構,索引存儲在一個易於遍歷讀取的數據集合中,索引是對數據庫表中一列或多列的值進行排序的一種結構
getIndexes 查看集合索引狀況
1
|
db
.col_name
.getIndexes()
|
hint 強制使用索引
1
|
db
.col_name
.find({
age:{$lt:
30}})
.hint({
name:
1, age:
1})
.explain()
|
刪除索引(不會刪除 _id 索引)
1
2
3
|
db
.col_name
.dropIndexes()
db
.col_name
.dropIndex({
firstname:
1})
|
MongoDB使用 createIndex() 方法來建立索引
key 爲你要建立的索引字段,1爲按升序建立索引,-1爲按降序建立索引。
也能夠設置使用多個字段建立索引(關係型數據庫中稱做複合索引)
1
|
db
.col_name
.createIndex({
key:
1})
|
createIndex() 接收可選參數,可選參數列表以下:
對於每一個插入的數據,都會自動生成一條惟一的 _id 字段,_id 索引是絕大多數集合默認創建的索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
> db
.col_1
.insert({x:
10})
WriteResult({ "nInserted" : 1 })
> db
.col_1
.find()
{
"_id" : ObjectId(
"59658e56aaf42d1c98dd95a2"),
"x" :
10 }
> db
.col_1
.getIndexes()
[
{
"v" :
2,
"key" : {
"_id" :
1
},
"name" :
"_id_",
"ns" :
"runoob.col_1"
}
]
|
字段解釋:
v 表示 version,在 Mongo3.2 以前的版本中,會存在 {v:0}(版本鎖爲0)的狀況。在3.2以後的版本中,{v:0} 再也不容許使用,這部分能夠不去關注,由於 v 由系統自動管理
key 表示做爲索引的鍵。1 或 -1表示排序模式,1爲升序,1爲降序
name 表示索引的名字,默認生成名稱的規則是做爲索引的字段_排序模式
ns 表示 namespace 命名空間,由數據庫名稱.集合名稱
組成
最普通的索引,不會自動建立
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
// 對 x 字段建立升序索引
> db
.col_1
.createIndex({x:
1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" :
1,
"numIndexesAfter" :
2,
"ok" :
1
}
> db
.col_1
.find()
{
"_id" : ObjectId(
"59658e56aaf42d1c98dd95a2"),
"x" :
10 }
> db
.col_1
.getIndexes()
[
{
"v" :
2,
"key" : {
"_id" :
1
},
"name" :
"_id_",
"ns" :
"runoob.col_1"
},
{
"v" :
2,
"key" : {
"x" :
1
},
"name" :
"x_1",
"ns" :
"runoob.col_1"
}
]
|
單鍵索引的值爲一個單一的值,多鍵索引的值有多個數據(如數組)
若是mongoDB中插入數組類型的多鍵數據,索引是自動創建的,無需刻意指定
1
2
3
4
5
6
7
8
9
10
|
> db
.col_1
.insert({z:[
1,
2,
3,
4,
5]})
WriteResult({ "nInserted" : 1 })
> db
.col_1
.find()
{
"_id" : ObjectId(
"59658e56aaf42d1c98dd95a2"),
"x" :
10 }
{
"_id" : ObjectId(
"5965923eaaf42d1c98dd95a3"),
"y" :
20 }
{
"_id" : ObjectId(
"59659828aaf42d1c98dd95a4"),
"z" : [
1,
2,
3,
4,
5 ] }
> db
.col_1
.find({z:
3})
{
"_id" : ObjectId(
"59659828aaf42d1c98dd95a4"),
"z" : [
1,
2,
3,
4,
5 ] }
|
同時對多個字段建立索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
> db
.col_2
.insert({x:
10,y:
20,z:
30})
WriteResult({ "nInserted" : 1 })
> db
.col_2
.find()
{
"_id" : ObjectId(
"59659a57aaf42d1c98dd95a5"),
"x" :
10,
"y" :
20,
"z" :
30 }
> db
.col_2
.createIndex({x:
1,y:
1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" :
1,
"numIndexesAfter" :
2,
"ok" :
1
}
> db
.col_2
.getIndexes()
[
{
"v" :
2,
"key" : {
"_id" :
1
},
"name" :
"_id_",
"ns" :
"runoob.col_2"
},
{
"v" :
2,
"key" : {
"x" :
1,
"y" :
1
},
"name" :
"x_1_y_1",
"ns" :
"runoob.col_2"
}
]
|
又稱 TTL(Time To Live,生存時間)索引,即在一段時間後會過時的索引(如登陸信息、日誌等)
過時後的索引會連同文檔一塊兒刪除
expireAfterSeconds:指定一個以秒爲單位的數值,設定集合的生存時間。
注意:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
> db
.col_3
.insert({x:new Date()})
WriteResult({ "nInserted" : 1 })
> db
.col_3
.find()
{
"_id" : ObjectId(
"59659f3baaf42d1c98dd95a7"),
"x" : ISODate(
"2017-07-12T04:02:03.835Z") }
> db
.col_3
.createIndex({x:
1},{expireAfterSeconds:
10})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" :
1,
"numIndexesAfter" :
2,
"ok" :
1
}
> db
.col_3
.getIndexes()
[
{
"v" :
2,
"key" : {
"_id" :
1
},
"name" :
"_id_",
"ns" :
"runoob.col_3"
},
{
"v" :
2,
"key" : {
"x" :
1
},
"name" :
"x_1",
"ns" :
"runoob.col_3",
"expireAfterSeconds" :
10
}
]
> db
.col_3
.find()
// 無返回
|
場景:全網站關鍵詞搜索
key-value 中,key 此時爲 $**
(也能夠是具體某 key),value 此時爲一個固定的字符串(如 text
)
全文索引類似度,與 sort 函數一塊兒使用效果更好
1
|
db.col_7.find({ $text: { $search:
"aa bb" } }, { score: { $meta:
"textScore" } }).sort({ score: { $meta:
"textScore" } })
|
注意:
或
非
與
(需用 \ 轉義)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
> db.col_7.find()
{
"_id" : ObjectId(
"5965aa84aaf42d1c98dd95b0"),
"title" :
"aa bb cc",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
{
"_id" : ObjectId(
"5965aa8faaf42d1c98dd95b1"),
"title" :
"abc def",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
{
"_id" : ObjectId(
"5965aedfaaf42d1c98dd95b2"),
"title" :
"aa bb",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
> db.col_7.createIndex({
"title":
"text"})
> db.col_7.find({$text:{$search:
"aa"}})
{
"_id" : ObjectId(
"5965aa84aaf42d1c98dd95b0"),
"title" :
"aa bb cc",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
{
"_id" : ObjectId(
"5965aedfaaf42d1c98dd95b2"),
"title" :
"aa bb",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
> db.col_7.find({$text:{$search:
"aa cc"}})
{
"_id" : ObjectId(
"5965aa84aaf42d1c98dd95b0"),
"title" :
"aa bb cc",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
{
"_id" : ObjectId(
"5965aedfaaf42d1c98dd95b2"),
"title" :
"aa bb",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
> db.col_7.find({$text:{$search:
"\"aa\
" \"cc\
""}})
{
"_id" : ObjectId(
"5965aa84aaf42d1c98dd95b0"),
"title" :
"aa bb cc",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
> db.col_7.find({$text:{$search:
"aa bb"}},{score:{$meta:
"textScore"}}).sort({score:{$meta:
"textScore"}})
{
"_id" : ObjectId(
"5965aedfaaf42d1c98dd95b2"),
"title" :
"aa bb",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》",
"score" :
1.5 }
{
"_id" : ObjectId(
"5965aa84aaf42d1c98dd95b0"),
"title" :
"aa bb cc",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》",
"score" :
1.3333333333333333 }
> db.col_7.dropIndexes()
> db.col_7.createIndex({
"author":
"text"}))
> db.col_7.find({$text:{$search:
"小明"}})})
>
> db.col_7.find({$text:{$search:
"白小明"}})
{
"_id" : ObjectId(
"5965aa84aaf42d1c98dd95b0"),
"title" :
"aa bb cc",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
{
"_id" : ObjectId(
"5965aa8faaf42d1c98dd95b1"),
"title" :
"abc def",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
{
"_id" : ObjectId(
"5965aedfaaf42d1c98dd95b2"),
"title" :
"aa bb",
"author" :
"白小明",
"article" :
"這是白小明的一篇文章,標題《aa bb cc》" }
|
查看最近的點
==分組計算==
MongoDB 中聚合主要用於處理數據(如平均值,求和等),並返回計算後的數據結果。相似sql語句中的 count(*)。
1
|
db
.col_name
.aggregate(AGGREGATE_OPERATION)
|
下表展現了一些聚合的表達式:
計算每一個做者所寫的文章數
在下面的例子中,咱們經過字段by_user字段對數據進行分組,並計算by_user字段相同值的總和。
集合中的數據以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
{
"_id" : ObjectId(
"5963b992a812aa05b9d2e765"),
"title" :
"MongoDB Overview",
"description" :
"MongoDB is no sql database",
"by_user" :
"runoob.com",
"url" :
"http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" :
100
}
{
"_id" : ObjectId(
"5963b9aaa812aa05b9d2e766"),
"title" :
"NoSQL Overview",
"description" :
"No sql database is very fast",
"by_user" :
"runoob.com",
"url" :
"http://www.runoob.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" :
10
}
{
"_id" : ObjectId(
"5963b9bba812aa05b9d2e767"),
"title" :
"Neo4j Overview",
"description" :
"Neo4j is no sql database",
"by_user" :
"Neo4j",
"url" :
"http://www.neo4j.com",
"tags" : [
"neo4j",
"database",
"NoSQL"
],
"likes" :
750
}
|
使用aggregate()計算結果以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
db.col_1.aggregate([{
$
group: {
_id:
"$by_user",
num_tutorial: {
$
sum:
1
}
}
}])
// 返回
{
"_id" :
"Neo4j",
"num_tutorial" :
1 }
{
"_id" :
"runoob.com",
"num_tutorial" :
2 }
// 以上實例相似sql語句
select by_user,
count(*)
from col_1
group
by by_user
|
管道在Unix和Linux中通常用於將當前命令的輸出結果做爲下一個命令的參數。
MongoDB 的聚合管道將MongoDB文檔在一個管道處理完畢後將結果傳遞給下一個管道處理。管道操做是能夠重複的。
表達式:處理輸入文檔並輸出。表達式是無狀態的,只能用於計算當前聚合管道的文檔,不能處理其它的文檔。
聚合管道經常使用的幾個操做:
$project 實例
0 爲不顯示,1爲顯示,默認狀況下 _id 字段是 1
1
2
3
4
5
6
7
8
9
10
11
12
|
db.articles.aggregate({
$project: {
_id:
0,
title:
1,
by_user:
1,
}
});
// 返回
{
"title" :
"MongoDB Overview",
"by_user" :
"runoob.com" }
{
"title" :
"NoSQL Overview",
"by_user" :
"runoob.com" }
{
"title" :
"Neo4j Overview",
"by_user" :
"Neo4j" }
|
$match 實例
$match 用於獲取分數大於70小於或等於90記錄,而後將符合條件的記錄送到下一階段$group管道操做符進行處理。
1
2
3
4
5
6
7
|
db.articles.aggregate([
{ $match: { score: { $gt:
70, $lte:
90 } } },
{ $group: { _id: null, count: { $sum:
1 } } }
]);
// 返回
{
"_id" : null,
"count" :
1 }
|
$skip 實例
通過 $skip 管道操做符處理後,前2個文檔被」過濾」掉。
1
|
db
.col_1
.aggregate({
$skip:
2 });
|
MongoDB 複製(副本集)是==將數據同步在多個服務器==的過程。
複製提供了數據的冗餘備份,並在多個服務器上存儲數據副本,提升了數據的可用性, 並能夠保證數據的安全性。
特色:
分佈式讀取數據
N 個節點的集羣
mongodb 的複製至少須要兩個節點。
mongodb各個節點常見的搭配方式爲:一主一從、一主多從。
主節點記錄在其上的全部操做oplog,從節點按期輪詢主節點獲取這些操做,而後對本身的數據副本執行這些操做,從而保證從節點的數據與主節點一致。
如今咱們經過指定 –replSet 選項來啓動mongoDB
1
|
mongod
--port
"PORT"
--dbpath
"YOUR_DB_DATA_PATH"
--replSet
"REPLICA_SET_INSTANCE_NAME"
|
實例:
下面實例會啓動一個名爲rs0的MongoDB實例,其端口號爲27017。
啓動後打開命令提示框並鏈接上mongoDB服務。
在Mongo客戶端使用命令rs.initiate()來啓動一個新的副本集。
咱們可使用rs.conf()來查看副本集的配置
查看副本集狀態使用 rs.status() 命令
1
|
mongod
--port
27017
--dbpath
"D:\set up\mongodb\data"
--replSet
rs0
|
添加副本集的成員,咱們須要使用多條服務器來啓動mongo服務。
進入Mongo客戶端,並使用rs.add()方法來添加副本集的成員。
1
|
rs
.add(
HOST_NAME
:PORT)
|
實例:
假設你已經啓動了一個名爲 mongod1.net,端口號爲27017的Mongo服務。
在客戶端命令窗口使用rs.add() 命令將其添加到副本集中,命令以下所示:
1
|
rs
.add("
mongod1
.net
:27017")
|
MongoDB 中你只能經過主節點將Mongo服務添加到副本集中, 判斷當前運行的Mongo服務是否爲主節點可使用命令
1
|
db
.isMaster()
|
MongoDB的副本集與咱們常見的主從有所不一樣,主從在主機宕機後全部服務將中止,而副本集在主機宕機後,副本會接管主節點成爲主節點,不會出現宕機的狀況。
當MongoDB存儲海量的數據時,==一臺機器可能不足以存儲數據==,也可能不足以提供可接受的讀寫吞吐量。這時,咱們就能夠經過在多臺機器上分割數據,使得數據庫系統能存儲和處理更多的數據。
爲何使用分片?
三個主要組件:
監控能夠了解 MongoDB 的==運行狀況==及==性能==
MongoDB中提供了 mongostat 和 mongotop 兩個命令來監控MongoDB的運行狀況。
它會間隔固定時間獲取 mongodb 的當前運行狀態,並輸出。
若是你發現數據庫忽然變慢或者有其餘問題的話,你第一手的操做就考慮採用 mongostat 來查看 mongo 的狀態。
1
|
mongostat
|
mongotop用來跟蹤MongoDB的實例,提供每一個集合的統計數據。默認狀況下,mongotop每一秒刷新一次。
1
|
mongotop
|
輸出結果字段說明:
等待的時間長度,以秒爲單位,默認 1s
1
|
mongotop
10
|
報告每一個數據庫的鎖的使用
1
|
mongotop
--locks
|
在Mongodb中咱們使用 mongodump
命令來備份MongoDB數據。
該命令能夠導出全部數據到指定目錄中。
mongodump命令能夠經過參數指定導出的數據量級轉存的服務器。
1
2
3
4
5
|
mongodump
-h
dbhost
-d
dbname
-o
dbdirectory
-h:
MongDB所在服務器地址,例如:127
.0
.0
.1,固然也能夠指定端口號:127
.0
.0
.1
:27017
-d:須要備份的數據庫實例,例如:
test
-o:備份的數據存放位置,例如:
c:\
data\
dump,固然該目錄須要提早創建,在備份完成後,系統自動在
dump目錄下創建一個
test目錄,這個目錄裏面存放該數據庫實例的備份數據。
|
備份 mongodb_study 數據庫中的全部集合到 E:\MongoDB\dump
1
|
mongodump
-h 127
.0
.0
.1
-d
mongodb_study
-o
E:\
MongoDB\
dump
|
不帶任何參數,即在當前目錄下備份全部數據庫實例
1
|
mongodump
|
備份全部MongoDB數據
1
2
3
4
|
mongodump
--host HOST_NAME
--port PORT_NUMBER
// 如
mongodump
--host w3cschool.cc
--port 27017
|
備份指定數據庫的集合
1
2
3
4
|
mongodump
--collection COLLECTION_NAME
--db DB_NAME
// 如
mongodump
--collection mycol
--db test
|
在Mongodb中咱們使用 mongorestore
命令來恢復MongoDB數據。
1
2
3
4
5
6
7
|
mongorestore -h <hostname><:port> -d dbname <path>
-
-host <:port>, -h <:port>:MongoDB所在服務器地址,默認爲: localhost:27017
-
-db , -d :須要恢復的數據庫實例,例如:test,固然這個名稱也能夠和備份時候的不同,好比test2
-
-drop:恢復的時候,先刪除當前數據,而後恢復備份的數據。就是說,恢復後,備份後添加修改的數據都會被刪除,慎用哦!
<path>:mongorestore 最後的一個參數,設置備份數據所在位置,例如:c:\data\dump\test。你不能同時指定 <path> 和 --dir 選項,--dir也能夠設置備份目錄。
-
-dir:指定備份的目錄,你不能同時指定 <path> 和 --dir 選項。
|
恢復存放在 E:\MongoDB\dump 中的數據庫 mongodb_study,恢復先後的數據庫名沒必要相同
1
|
mongorestore -h localhost /db mongodb_study /dir E:
\MongoDB
\dump
\mongodb_study
|
與 MySQL 不一樣的是 MongoDB 會自動建立數據庫和集合,因此使用前咱們不須要手動去建立。
安裝驅動:npm install mongodb
運行 node:node connect
connect.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
const MongoClient =
require(
'mongodb').MongoClient;
// 自動建立數據庫 runoob
let mongoConnect =
'mongodb://localhost:27017/runoob';
// 插入數據,插入到數據庫 runoob 的 site 集合中
let insertData =
function(db, callback) {
// 自動建立集合 site
let collection = db.collection(
'site');
// 插入文檔
let data = [{
"name":
"菜鳥教程",
"url":
"www.runoob.com"
}, {
"name":
"菜鳥工具",
"url":
"c.runoob.com"
}];
collection.insert(data,
function(err, result) {
if (err) {
console.log(
'Error:' + err);
return;
}
callback(result);
});
};
// 刪除數據,刪除全部 name 爲 "菜鳥工具" 的文檔
let deleteData =
function(db, callback) {
let collection = db.collection(
'site');
let whereStr = {
"name":
"菜鳥工具"
};
collection.remove(whereStr,
function(err, result) {
if (err) {
console.log(
'Error:' + err);
return;
}
callback(result);
});
};
// 修改數據,將因此 name 爲 "菜鳥教程" 的 url 改成 https://www.runoob.com
let updateData =
function(db, callback) {
let collection = db.collection(
'site');
let whereStr = {
"name":
"菜鳥教程"
};
let updateStr = {
$set: {
"url":
"https://www.runoob.com"
}
};
collection.update(whereStr, updateStr, {
multi:
true
},
function(err, result) {
if (err) {
console.log(
'Error:' + err);
return;
}
callback(result);
});
};
// 查詢數據,查詢 name 爲 "菜鳥教程" 的數據
let selectData =
function(db, callback) {
let collection = db.collection(
'site');
let whereStr = {
"name":
'菜鳥教程'
};
collection.find(whereStr).toArray(
function(err, result) {
if (err) {
console.log(
'Error:' + err);
return;
}
callback(result);
});
};
MongoClient.connect(mongoConnect,
function(err, db) {
console.log(
"鏈接成功!");
insertData(db,
function(result) {
console.log(
"插入數據成功!");
console.log(result);
db.close();
});
deleteData(db,
function(result) {
console.log(
"刪除數據成功!");
console.log(result);
db.close();
});
updateData(db,
function(result) {
console.log(
"修改數據成功!");
console.log(result);
db.close();
});
selectData(db,
function(result) {
console.log(
"查詢數據成功!");
console.log(result);
db.close();
});
});
|
Mongoose學習參考文檔——基礎篇:https://cnodejs.org/topic/504b4924e2b84515770103dd
mongoose學習筆記:https://cnodejs.org/topic/58b911997872ea0864fee313
mongoose學習文檔:http://www.cnblogs.com/y-yxh/p/5689555.html
Nodejs學習筆記(十四)— Mongoose介紹和入門:http://www.cnblogs.com/zhongweiv/p/mongoose.html
Mongoose全面理解:http://www.cnblogs.com/jayruan/p/5123754.html
Node.js 有針對 MongoDB 的數據庫驅動:mongodb。你可使用 npm install mongodb
來安裝。不過直接使用 mongodb 模塊雖然強大而靈活,但有些繁瑣,我就使用 mongoose 吧。
Mongoose 基於nodejs、構建在 mongodb 之上,使用 javascript 編程,是==鏈接 mongodb 數據庫的軟件包==,使mongodb的文檔數據模型變的優雅起來,方便對mongodb文檔型數據庫的鏈接和增刪改查等常規數據操做。
mongoose 是當前使用 mean(mongodb express angularjs nodejs)全棧開發必用的鏈接數據庫軟件包。
==mongoose ,提供了Schema、Model 和 Document 對象,用起來更爲方便。== 另外,mongoose 還有 Query 和 Aggregate 對象:Query 實現查詢、Aggregate 實現聚合
Schema、Model、Entity 的關係:Schema生成Model,Model創造Entity,Model和Entity均可對數據庫操做形成影響,但Model比Entity更具操做性。
Schema 對象定義==文檔結構==,能夠定義字段、類型、惟一性、索引、驗證等。
Schema 不只定義了文檔結構和使用性能,還能夠有擴展插件、實例方法、靜態方法、複合索引、文檔生命週期鉤子
1
2
3
4
5
|
// new mongoose.Schema() 中傳入一個 JSON 對象,定義屬性和屬性類型
var BlogSchema =
new mongoose.Schema({
title:
String,
author:
String
});
|
有的時候,咱們創造的 Schema 不只要爲後面的 Model 和 Entity 提供公共的屬性,還要提供公共的方法。
Model 對象表示集合中的全部文檔
由 Schema 發佈生成的模型,具備抽象屬性和行爲的數據庫操做對
Document 可等同於 Entity
由 Model 建立的實體,他的操做也會影響數據庫
mongoose 的 connection 對象定義了一些事件,好比 connected open close error 等,咱們能夠監聽這些事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
const mongoose =
require(
'mongoose');
let db = mongoose.connect(
'mongodb://127.0.0.1:27017/test');
db.connection.on(
'error',
console.error.bind(
console,
'數據庫鏈接失敗:'));
db.connection.once(
'open',
function() {
console.log(
'數據庫鏈接成功!');
// 定義一個 Schema 模式
// new Schema() 中傳入一個 JSON 對象,定義屬性和屬性類型
let PersonSchema =
new mongoose.Schema({
name: {
type:
String,
unique:
true
},
password:
String
});
// 將該 Schema 發佈爲 Model
let PersonModel = mongoose.model(
'col_1', PersonSchema);
// 拿到了 Model 對象,就能夠執行增刪改查等操做了
// 若是要執行查詢,須要依賴 Model,固然 Entity 也是能夠作到的
PersonModel.find(
function(err, result) {
// 查詢到的全部person
});
// 用 Model 建立 Entity
let personEntity =
new PersonModel({
name:
'Krouky',
password:
'10086'
});
// Entity 是具備具體的數據庫操做 CRUD 的
// 執行完成後,數據庫就有該數據了
personEntity.save(
function(err, result) {
if (err) {
console.log(err);
}
else {
console.log(
`${result} saved!`);
}
});
});
|