《MongoDB權威指南》讀書筆記

插入文檔

使用insert向集合中插入一個文檔:

1
2
3
4
> db.test.insert({"name":"mrbird"})
WriteResult({ "nInserted" : 1 })
> db.test.findOne()
{ "_id" : ObjectId("58a99b8168e0d7b9f6992c69"), "name" : "mrbird" }

插入的文檔沒有“_id”鍵的話,這個操作會自動爲文檔添加一個“_id”鍵。 批量插入文檔則需使用insertMany函數,函數接收一個文檔數組:

1
2
3
4
5
6
7
8
9
10
11
12
> db.test.insertMany([{"name":"Jane"},{"name":"KangKang"}])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("58a99d6468e0d7b9f6992c6b"),
ObjectId("58a99d6468e0d7b9f6992c6c")
]
}
> db.test.find()
{ "_id" : ObjectId("58a99b8168e0d7b9f6992c69"), "name" : "mrbird" }
{ "_id" : ObjectId("58a99d6468e0d7b9f6992c6b"), "name" : "Jane" }
{ "_id" : ObjectId("58a99d6468e0d7b9f6992c6c"), "name" : "KangKang" }

要查看一個文檔的大小,可以使用Object.bsonsize(doc)函數(單位爲字節):

1
2
> Object.bsonsize(db.test.find({"name":"mrbird"}))
1215

刪除文檔

刪除文檔使用remove函數,接收一個查詢文檔,所有匹配的文檔都將會被刪除:

1
2
3
4
5
> db.test.remove({"name":"mrbird"})
WriteResult({ "nRemoved" : 1 })
> db.test.find()
{ "_id" : ObjectId("58a99d6468e0d7b9f6992c6b"), "name" : "Jane" }
{ "_id" : ObjectId("58a99d6468e0d7b9f6992c6c"), "name" : "KangKang" }

要清空整個集合的話,可以使用drop函數:

1
2
3
> db.test.drop()
true
> db.test.find()

更新文檔

使用update函數更新文檔,接收兩個參數,查詢文檔和修改器文檔,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> db.test.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird.leanote.com"
}
> var mrbird = db.test.findOne({"name":"mrbird"})
> mrbird.blog = "mrbird's blog"
mrbird's blog
> db.test.update({"name":"mrbird"},mrbird)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird's blog"
}

$inc修改器用來增加或減少已有的鍵值,如果該鍵不存在則創造一個。比如:

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
> db.test.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird's blog"
}
> db.test.update({"name":"mrbird"},{"$inc":{"pageview":1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird's blog",
"pageview" : 1
}
> db.test.update({"name":"mrbird"},{"$inc":{"pageview":100}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird's blog",
"pageview" : 101
}
> db.test.update({"name":"mrbird"},{"$inc":{"pageview":-50}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird's blog",
"pageview" : 51
}

$inc只能用於整型,長整型或雙精度浮點型的值。

$set用於修改文檔的字段值,當這個字段不存在的時候就創建一個。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
> db.test.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird's blog",
"pageview" : 51
}
> db.test.update({"_id":ObjectId("58a9ace92363ff29a7d881e9")},
... {"$set":{"note":"love leanote!!"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test.findOne({"_id":ObjectId("58a9ace92363ff29a7d881e9")})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird's blog",
"pageview" : 51,
"note" : "love leanote!!"
}

$set還可以修改鍵的類型,比如將note鍵的值改爲數組類型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> db.test.update({"_id":ObjectId("58a9ace92363ff29a7d881e9")},
... {"$set":{"note":["love leanote","the fun of code"]}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test.findOne({"_id":ObjectId("58a9ace92363ff29a7d881e9")})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird's blog",
"pageview" : 51,
"note" : [
"love leanote",
"the fun of code"
]
}

$set也可以修改內嵌文檔,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> db.blog.findOne()
{
"_id" : ObjectId("58aa47f645b899838bfb6114"),
"name" : "mrbird's blog",
"post" : "mongodb",
"comment" : {
"name" : "xiaohema",
"msg" : "學習了,感謝分享"
}
}
> db.blog.update({"name":"mrbird's blog"},
... {"$set":{"comment.msg":"好,支持威武有希望了"}})
> db.blog.findOne()
{
"_id" : ObjectId("58aa47f645b899838bfb6114"),
"name" : "mrbird's blog",
"post" : "mongodb",
"comment" : {
"name" : "xiaohema",
"msg" : "好,支持威武有希望了"
}
}

使用$unset可刪除鍵,比如:

1
2
3
4
5
6
7
8
9
10
> db.test.update({"_id":ObjectId("58a9ace92363ff29a7d881e9")},
... {"$unset":{"note":1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.test.findOne({"_id":ObjectId("58a9ace92363ff29a7d881e9")})
{
"_id" : ObjectId("58a9ace92363ff29a7d881e9"),
"name" : "mrbird",
"blog" : "mrbird's blog",
"pageview" : 51
}

數組修改器

$push會向已有的數組末尾添加一個值,如果數組不存在,則創建該數組。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
> db.blog.findOne()
{
"_id" : ObjectId("58aa47f645b899838bfb6114"),
"name" : "mrbird's blog",
"post" : "mongodb"
}
> db.blog.update({"name":"mrbird's blog"}, {"$push":
...{"comments": {"name":"ltsc","msg":"不明覺厲"}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.blog.findOne()
{
"_id" : ObjectId("58aa47f645b899838bfb6114"),
"name" : "mrbird's blog",
"post" : "mongodb",
"comments" : [
{
"name" : "ltsc",
"msg" : "不明覺厲"
}
]
}

如果要一次性向數組中添加多個值,可以使用$push結合$each修改器。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
> db.blog.update({"name":"mrbird's blog"},
... {"$push":{"comments":{"$each":[
... {"name":"Althars","msg":"siguoyi"},
... {"name":"jint","msg":"厲害了我的哥"}]}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.blog.findOne()
{
"_id" : ObjectId("58aa47f645b899838bfb6114"),
"name" : "mrbird's blog",
"post" : "mongodb",
"comments" : [
{
"name" : "ltsc",
"msg" : "不明覺厲"
},
{
"name" : "Althars",
"msg" : "siguoyi"
},
{
"name" : "jint",
"msg" : "厲害了我的哥"
}
]

$slice可以在爲數組添加值的時候截取數組,但必須配合$push$each一起使用,否則報語法錯誤,比如:

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
> db.user.findOne()
{
"_id" : ObjectId("58aa5e8a6a294f5543ff66eb"),
"name" : "KangKang",
"sex" : "male",
"habbit" : [
"basketball",
"football",
"swimming",
"running"
]
}
> db.user.update({"name":"KangKang"},
... {"$push":{"habbit":{"$each":
... ["eating"],"$slice":-3}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.findOne()
{
"_id" : ObjectId("58aa5e8a6a294f5543ff66eb"),
"name" : "KangKang",
"sex" : "male",
"habbit" : [
"swimming",
"running",
"eating"
]
}

從結果可以看出,$slice截取了數組最新的三個值。注意,$slice的值必須是負整數。

現在有這麼一種情況,$push修改器可以向一個數組中添加重複的值,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> db.user.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58aa7cb06a294f5543ff66ec"),
"name" : "mrbird",
"email" : [
]
}
> db.user.update({"name":"mrbird"}, {"$push":{"email":"[email protected]"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58aa7cb06a294f5543ff66ec"),
"name" : "mrbird",
"email" : [
]
}

如果希望數組中添加的值不重複的話,可以使用$addToSet修改器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> db.user.update({"name":"mrbird"}, {"$unset":{"email":1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.findOne({"name":"mrbird"})
{ "_id" : ObjectId("58aa7cb06a294f5543ff66ec"), "name" : "mrbird" }
> db.user.update({"name":"mrbird"},
... {"$addToSet":{"email":{"$each":["[email protected]","[email protected]","[email protected]"]}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58aa7cb06a294f5543ff66ec"),
"name" : "mrbird",
"email" : [
]
}

刪除數組元素有幾種方法,比如$pop{“$pop”:{"key":1}}表示從數組尾部刪除元素,-1則表示從頭部刪除:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> db.user.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58aa7cb06a294f5543ff66ec"),
"name" : "mrbird",
"email" : [
]
}
> db.user.update({"name":"mrbird"},
... {"$pop":{"email":1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.findOne({"name":"mrbird"})
{
"_id" : ObjectId("58aa7cb06a294f5543ff66ec"),
"name" : "mrbird",
"email" : [
]
}

另外一個刪除數組元素的修改器爲$pull,該操作符會將所有匹配的元素從數組中刪除。比如:

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
> db.user.update({"name":"KangKang"},
... {"$push":{"habbit":"eating"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.findOne({"name":"KangKang"})
{
"_id" : ObjectId("58aa5e8a6a294f5543ff66eb"),
"name" : "KangKang",
"sex" : "male",
"habbit" : [
"swimming",
"running",
"eating",
"eating"
]
}
> db.user.update({"name":"KangKang"},
... {"$pull":{"habbit":"eating"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.findOne({"name":"KangKang"})
{
"_id" : ObjectId("58aa5e8a6a294f5543ff66eb"),
"name" : "KangKang",
"sex" : "male",
"habbit" : [
"swimming",
"running"
]
}

還可以通過數組的下標修改數組內容,如下所示:

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
> db.blog.find({"name":"mrbird's blog"}).pretty()
{
"_id" : ObjectId("58aa47f645b899838bfb6114"),
"name" : "mrbird's blog",
"post" : "mongodb",
"comments" : [
{
"name" : "ltsc",
"msg" : "不明覺厲"
},
{
"name" : "Althars",
"msg" : "siguoyi"
},
{
"name" : "jint",
"msg" : "厲害了我的哥"
}
]
}
> db.blog.update({"name":"mrbird's blog"},
... {"$set":{"comments.1.msg":"四國以"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.blog.find({"name":"mrbird's blog"}).pretty()
{
"_id" : ObjectId("58aa47f645b899838bfb6114"),
"name" : "mrbird's blog",
"post" : "mongodb",
"comments" : [
{
"name" : "ltsc",
"msg" : "不明覺厲"
},
{
"name" : "Althars",
"msg" : "四國以"
},
{
"name" : "jint",
"msg" : "厲害了我的哥"
}
]
}

這種做法有侷限性,就是必須先知道待修改字段的數組下標,可以使用另外一種方法,下面這種方法只需要知道待修改字段就行了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> db.blog.update({"comments.msg":"四國以"},
... {"$set":{"comments.$.msg":"看完此文,猶如醍醐灌頂"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.blog.find({"name":"mrbird's blog"}).pretty()
{
"_id" : ObjectId("58aa47f645b899838bfb6114"),
"name" : "mrbird's blog",
"post" : "mongodb",
"comments" : [
{
"name" : "ltsc",
"msg" : "不明覺厲"
},
{
"name" : "Althars",
"msg" : "看完此文,猶如醍醐灌頂"
},
{
"name" : "jint",
"msg" : "厲害了我的哥"
}
]
}

update函數的第三個參數爲upsert,設置爲true時,新一個文檔,沒有找到匹配的查詢文檔時,插入該文檔,找到了就更新,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> db.blog.findOne({"name":"mrbrid","post":"MongoDB文檔CUD"})
null
> db.blog.update({"name":"mrbrid","post":"MongoDB文檔CUD"},
... {"$inc":{"pageview":1}},true)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("58acf0743c8ad0b0d9d65f45")
})
> db.blog.findOne({"name":"mrbrid","post":"MongoDB文檔CUD"})
{
"_id" : ObjectId("58acf0743c8ad0b0d9d65f45"),
"name" : "mrbrid",
"post" : "MongoDB文檔CUD",
"pageview" : 1
}

update函數的第四個參數爲multi,設置爲true的時候,批量更新和查詢文檔匹配的文檔,比如將mrbird’s blog集合中所有文檔的pageview增加1:

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
> db.blog.find().pretty()
{
"_id" : ObjectId("58acf0743c8ad0b0d9d65f45"),
"name" : "mrbird's blog",
"post" : "MongoDB文檔CUD",
"pageview" : 1
}
{
"_id" : ObjectId("58acf64b3c8ad0b0d9d65f4a"),
"name" : "mrbird's blog",
"post" : "MongoDB shell",
"pageview" : 1
}
{
"_id" : ObjectId("58acf65d3c8ad0b0d9d65f4d"),
"name" : "mrbird's blog",
"post" : "start Spring Boot",
"pageview" : 1
}
> db.blog.update({"name":"mrbird's blog"},{"$inc":{"pageview":1}},
... false,true)
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })
> db.blog.find().pretty()
{
"_id" : ObjectId("58acf0743c8ad0b0d9d65f45"),
"name" : "mrbird's blog",
"post" : "MongoDB文檔CUD",
"pageview" : 2
}
{
"_id" : ObjectId("58acf64b3c8ad0b0d9d65f4a"),
"name" : "mrbird's blog",
"post" : "MongoDB shell",
"pageview" : 2
}
{
"_id" : ObjectId("58acf65d3c8ad0b0d9d65f4d"),
"name" : "mrbird's blog",
"post" : "start Spring Boot",
"pageview" : 2
}

另外,調用getLastError可查看最近一次更新的文檔數量,如:

1
2
3
4
5
6
7
8
9
10
> db.runCommand({getLastError:1})
{
"connectionId" : 1,
"updatedExisting" : true,
"n" : 3,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
}

擁有類似事務特性的更新與查詢操作findAndModify。它是原子性的,會返回符合查詢條件的更新後的文檔。一次最多隻更新一個文檔,也就是條件query條件,且執行sort後的第一個文檔。語法如下:

1
2
3
4
5
6
7
8
9
db.COLLECTION_NAME.findAndModify({
query:{},
update:{},
remove:true|false,
new:true|false,
sort:{},
fields:{},
upsert:true|false}
);​

  1. query是查詢選擇器,與findOne的查詢選擇器相同。

  2. update是要更新的值,不能與remove同時出現。

  3. remove表示刪除符合query條件的文檔,不能與update同時出現。

  4. new爲true:返回更新後的文檔,false:返回更新前的,默認是false。

  5. sort:排序條件,與sort函數的參數一致。

  6. fields:投影操作,與find的第二個參數一致。

  7. upsert:與update的upsert參數一樣。

例子:

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
> db.blog.findAndModify({
... "query":{"name":"mrbird's blog"},
... "update":{
... "$inc":{"pageview":1},
... "$set":{"like":1}}})
{
"_id" : ObjectId("58acf0743c8ad0b0d9d65f45"),
"name" : "mrbird's blog",
"post" : "MongoDB文檔CUD",
"pageview" : 3
}
> db.blog.find().pretty()
{
"_id" : ObjectId("58acf0743c8ad0b0d9d65f45"),
"name" : "mrbird's blog",
"post" : "MongoDB文檔CUD",
"pageview" : 4,
"like" : 1
}
{
"_id" : ObjectId("58acf64b3c8ad0b0d9d65f4a"),
"name" : "mrbird's blog",
"post" : "MongoDB shell",
"pageview" : 3
}
{
"_id" : ObjectId("58acf65d3c8ad0b0d9d65f4d"),
"name" : "mrbird's blog",
"post" : "start Spring Boot",
"pageview" : 3
}

可發現,執行findAndModify後,返回被更新前(默認顯示更新前的)的文檔,並且只更新了匹配的第一條文檔。

如果要返回被更新後的文檔,我們設置new 爲true:

1
2
3
4
5
6
7
8
9
10
11
> db.blog.findAndModify({
..."query":{"name":"mrbird's blog"},
..."update":{ "$inc":{"pageview":1}, "$set":{"like":2}},
..."new":true})
{
"_id" : ObjectId("58acf0743c8ad0b0d9d65f45"),
"name" : "mrbird's blog",
"post" : "MongoDB文檔CUD",
"pageview" : 5,
"like" : 2
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章