MongoDB權威指南第二版學習筆記(三)—增刪改文檔上

来源:http://www.cnblogs.com/ginb/archive/2016/12/16/6184916.html
-Advertisement-
Play Games

插入insert 單條插入 批量插入 如果在執行批量插入的過程中有一個文檔插入失敗,那麼在這個文檔之前的所有文檔都會插入成功,之後的所有全部失敗。 刪除文檔 remove remove函數接受一個查詢文檔作為參數。符合條件的文檔才被刪除。刪除數據是永久性的,不能撤銷,也不能恢復。 drop 要清空整 ...


插入insert

單條插入

> db.foo.insert({"bar":"baz"})
WriteResult({ "nInserted" : 1 })

批量插入

> db.foo.insert([{"_id":1},{"_id":2},{"_id":3}])
BulkWriteResult({
        "writeErrors" : [ ],
        "writeConcernErrors" : [ ],
        "nInserted" : 3,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})
> db.foo.find()
{ "_id" : 1 }
{ "_id" : 2 }
{ "_id" : 3 }
> 

如果在執行批量插入的過程中有一個文檔插入失敗,那麼在這個文檔之前的所有文檔都會插入成功,之後的所有全部失敗。

> db.foo.insert([{"_id":10},{"_id":11},{"_id":10},{"_id":12}])
BulkWriteResult({
        "writeErrors" : [
                {
                        "index" : 2,
                        "code" : 11000,
                        "errmsg" : "E11000 duplicate key error collection: test.foo index: _id_ dup key: { : 10.0 }",
                        "op" : {
                                "_id" : 10
                        }
                }
        ],
        "writeConcernErrors" : [ ],
        "nInserted" : 2,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})
> db.foo.find()
{ "_id" : 10 }
{ "_id" : 11 }
> 

刪除文檔

remove

remove函數接受一個查詢文檔作為參數。符合條件的文檔才被刪除。刪除數據是永久性的,不能撤銷,也不能恢復。

> db.foo.remove()
2016-12-15T19:50:31.721+0800 E QUERY    [thread1] Error: remove needs a query :
DBCollection.prototype._parseRemove@src/mongo/shell/collection.js:406:1
DBCollection.prototype.remove@src/mongo/shell/collection.js:433:18
@(shell):1:1

> db.foo.remove({"_id":10})
WriteResult({ "nRemoved" : 1 })
> db.foo.find()
{ "_id" : 11 }
> 

drop

要清空整個集合,那麼使用drop直接刪除集合會更快。代價是:不能指定任何限定條件。整個集合都被刪除,所有元數據都不見了。

> for(var i=0;i<1000000;i++){
... db.tester.insert({"foo":"bar","baz":i,"z":10-i})
... }
WriteResult({ "nInserted" : 1 })
> db.tester.find()
{ "_id" : ObjectId("58528543b049609a5fa74f7c"), "foo" : "bar", "baz" : 0, "z" : 10 }
......
Type "it" for more > db.tester.drop()//插入一百萬條數據,使用drop刪除,只需1ms true >

更新文檔update

Update有兩個必須參數:

一是查詢文檔,用於定位需要更新的目標文檔

二是修改器文檔,用於說明要找到的文檔進行哪些修改

更新操作是不可分割的:若是兩個更新同時發生,先到達伺服器的先執行,接著執行另一個。

db.foo.insert({
... "name":"yyb",
... "friends":32,
... "enemies":2
... })
WriteResult({ "nInserted" : 1 })
> db.foo.update({"name":"yyb"},{"name":"joe"})//將yyb這個文檔修改成{“name”:“joe”}
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.foo.find()
{ "_id" : ObjectId("58528a2bb049609a5fb691bc"), "name" : "joe" }
> 

文檔替換

用一個新文檔完全替換匹配的文檔,這適合大規模模式遷移的情況。

  db.user.insert({
... ... "name":"joe",
... ... "friends":32,
... ... "enemies":2
... ... })
WriteResult({ "nInserted" : 1 })
//將上面這個文檔的後兩個欄位移到子文檔為realtionships中
> var joe=db.user.findOne({"name":"joe"})
> joe.relationships={"friends":joe.friends,"enemies":joe.enemies};
{ "friends" : 32, "enemies" : 2 }
> delete joe.friends
true
> delete joe.enemies
true
> db.user.update({"name":"joe"},joe);
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("58529188b049609a5fb691bf"), "name" : "joe", "relationships" : { "friends" : 32, "enemies" : 2 } }
> 

常見的錯誤是查詢條件匹配到了多個文檔,然後更新時由於第二個參數的存在就產生重覆的 _id 值。資料庫會拋出異常。

> db.user.find()
{ "_id" : ObjectId("585295e3b049609a5fb691c5"), "name" : "yyb", "age" : 21 }
{ "_id" : ObjectId("585295e3b049609a5fb691c6"), "name" : "yyb", "age" : 30 }
{ "_id" : ObjectId("585295e3b049609a5fb691c7"), "name" : "yyb", "age" : 40 }
> joe=db.user.findOne({"name":"yyb","age":30})
{ "_id" : ObjectId("585295e3b049609a5fb691c6"), "name" : "yyb", "age" : 30 }
> joe.age++;
30
> db.user.update({"name":"yyb"},joe)
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 16837,
                "errmsg" : "The _id field cannot be changed from {_id: ObjectId('585295e3b049609a5fb691c5')} to {_id: ObjectId('585295e3b049609a5fb691c6')}."
        }
})
> 

使用修改器

使用原子性的更新修改器,指定對文檔的某些欄位進行更新。更新修改器是種特殊的鍵,用來指定複雜的更新操作,比如修改、添加或者刪除鍵,還可能是操作數組或者內嵌文檔。

> db.user.find()
{ "_id" : ObjectId("585295e3b049609a5fb691c5"), "name" : "yyb", "age" : 21 }
{ "_id" : ObjectId("585295e3b049609a5fb691c6"), "name" : "yyb", "age" : 30 }
{ "_id" : ObjectId("585295e3b049609a5fb691c7"), "name" : "yyb", "age" : 40 }
> db.user.update({"name":"yyb"},{$inc:{"age":5}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })> db.user.find({"name":"yyb"})
{ "_id" : ObjectId("585295e3b049609a5fb691c5"), "name" : "yyb", "age" : 26 }
{ "_id" : ObjectId("585295e3b049609a5fb691c6"), "name" : "yyb", "age" : 30 }
{ "_id" : ObjectId("585295e3b049609a5fb691c7"), "name" : "yyb", "age" : 40 }
> 

明明匹配3條,卻只改了一條。原來MongoDB預設只會更新匹配的第一條,如果要更新多條,還得指定參數。

使用修改器時,_id的值不能改變。(整個文檔替換時可以改變“_id”)

$set與$unset

用來指定一個欄位的值。如果這個欄位不存在,則創建它。

> db.user.insert({
... "name":"yyb",
... "age":20,
... "sex":"male",
... "location":"cd"})
WriteResult({ "nInserted" : 1 })
>> db.user.update({"name":"yyb"},{"$set":{"email":"[email protected]"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find().pretty()
{
        "_id" : ObjectId("58529e66b049609a5fb691c9"),
        "name" : "yyb",
        "age" : 20,
        "sex" : "male",
        "location" : "cd",
        "email" : "[email protected]"
}
> 

用 $set 甚至可以修改鍵的類型。用 $unset 可以將鍵完全刪除。

>  db.user.update(
... ... {"name":"yyb"},
... ... {"$set":{"email":["[email protected]","[email protected]"]}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find().pretty()
{
        "_id" : ObjectId("58529e66b049609a5fb691c9"),
        "name" : "yyb",
        "age" : 20,
        "sex" : "male",
        "location" : "cd",
        "email" : [
                "[email protected]",
                "[email protected]"
        ]
}
> db.user.update({"name":"yyb"},{"$unset":{"email":1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find().pretty()
{
        "_id" : ObjectId("58529e66b049609a5fb691c9"),
        "name" : "yyb",
        "age" : 20,
        "sex" : "male",
        "location" : "cd"
}

也可以用 $set 修改內嵌文檔:

{
        "_id" : ObjectId("5853e17ff7720722b4ded850"),
        "title" : "a blog post",
        "content" : "...",
        "author" : {
                "name" : "yyb",
                "email" : "[email protected]"
        }
}
> db.blog.update(
... {"author.name":"yyb"},
... {"$set":{"author.name":"joe"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.blog.findOne()
{
        "_id" : ObjectId("5853e17ff7720722b4ded850"),
        "title" : "a blog post",
        "content" : "...",
        "author" : {
                "name" : "joe",
                "email" : "[email protected]"
        }
}

增加、刪除、修改鍵時,應該使用$開頭的修改器,否則可能會將整個文檔替換掉。

$inc

 $inc 用來增加已有鍵的值,或者該鍵不存在那就創建一個。對於更新分析數據、因果關係、投票或者其他有變化數值的地方很方便。

> db.games.insert({"games":"pinball","user":"joe"})
WriteResult({ "nInserted" : 1 })
> db.games.update({"games":"pinball"},{"$inc":{"score":50}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.games.findOne()
{
        "_id" : ObjectId("5853e517f7720722b4ded851"),
        "games" : "pinball",
        "user" : "joe",
        "score" : 50
}
> db.games.update({"games":"pinball"},{"$inc":{"score":10000}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.games.findOne()
{
"_id" : ObjectId("5853e517f7720722b4ded851"),
"games" : "pinball",
"user" : "joe",
"score" : 10050
}
>

 $inc 就是專門用來增減數字的。且只能用於整型、長整型或者雙精度浮點型的值。其他類型的數據會操作失敗。

> db.foo.insert({"count":"1"})
WriteResult({ "nInserted" : 1 })

> db.foo.update({},{"$inc":{"count":1}})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 16837,
                "errmsg" : "Cannot apply $inc to a value of non-numeric type. {_id: ObjectId('5853e73df7720722b4ded853')} has the field 'count' of non-numeric type String"
        }
})
> 

 $inc 鍵的值必須為數字,不能使用字元串、數組或者其他非數字的值。要修改其他類型,應該使用 $set 或者數字修改器。

> db.foo.insert({"count":1})
WriteResult({ "nInserted" : 1 })

> db.foo.update({},{"$inc":{"count":"5"}})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 14,
                "errmsg" : "Cannot increment with non-numeric argument: {count: \"5\"}"
        }
})
> 

數組修改器

$push

$push 添加元素。如果數組已經存在,會向已有的數組末尾加入一個元素,要是沒有就創建一個新的數組。

> db.blog.post.findOne()
{
        "_id" : ObjectId("5853ea01f7720722b4ded855"),
        "title" : "a blog post",
        "content" : "..."
}
> db.blog.post.update(
... {"title":"a blog post"},
... {"$push":{"comments":{"name":"joe","email":"[email protected]","content":"nice post"}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.blog.post.findOne()
{
        "_id" : ObjectId("5853ea01f7720722b4ded855"),
        "title" : "a blog post",
        "content" : "...",
        "comments" : [
                {
                        "name" : "joe",
                        "email" : "[email protected]",
                        "content" : "nice post"
                }
        ]
}
> 
> db.blog.post.update(
... {"title":"a blog post"},
... {"$push":{"comments":{"name":"bob","email":"

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 苦心人天不負, 為了項目終於把 iOS 10 跳轉系統設置的方法給搞定了, 很欣慰. http://www.cnblogs.com/lurenq/p/6189580.html iOS 10 跳轉系統設置的欄位 電池電量 Prefs:root=BATTERY_USAGE 通用設置 Prefs:root ...
  • 從今天開始研究開發自己的編程語言Ocelot,從《自製編譯器》出發,然後再自己不斷完善功能並優化。 編譯器前端簡單,就不深入研究了,直接用現成的一款工具叫JavaCC,它可以生成抽象語法樹,抽象語法樹是生成中間代碼的關鍵,而中間代碼又是生成後端代碼的關鍵。 整個編譯器代碼採用java語言編寫,主要功 ...
  • 本文用於收集在運維中經常使用的系統內置函數,持續整理中 一,常用Metadata函數 1,查看資料庫的ID和Name 2,查看對象的ID和Name,對象的Schema,對象的定義 3,查看Schema的ID和Name,通過對象ID獲取對象的架構名(Schema) 4,查看Column的Name 二, ...
  • 基本概念: 資料庫DB(database): + 數據的倉庫,數據的集合,是數據的一種結構化的存儲 資料庫管理系統DBMS(database management system): + 管理資料庫的一套軟體 + 比如Oracle、MySQL、SQL server、DB2 + 介於應用程式和操作系統之 ...
  • 本文出處:http://www.cnblogs.com/wy123/p/6189100.html 標題有點拗口, 先拋出問題:一個查詢沒有明確指定排序方式,那麼,第二次執行這個同樣的查詢的時候,查詢結果會不會與第一次的查詢結果排序方式完全一樣? 答案是不確定的,兩個完全一樣的查詢,結果也完全一樣,兩 ...
  • List Publishers = new List(); Publisher publish1 = new Publisher(); publish1.Code = "01"; publish1.Name = "北京出版社1"; Publishers.Add(publish1); ... ...
  • ORAchk概述 ORAchk是Oracle官方出品的Oracle產品健康檢查工具,可以從MOS(My Oracle Support)網站上下載,免費使用。這個工具可以檢查Oracle資料庫,GoldenGate,Oracle Enterprise Manager 12c、13c等Oracle產品, ...
  • 一:redis的安裝 1、 首先上官網下載Redis 壓縮包,地址:http://redis.io/download 下載 2、 通過遠程管理工具,將壓縮包拷貝到Linux伺服器中,執行解壓操作 3、 進入redis目錄執行make 對Redis解壓後文件進行編譯 4、 編譯完成之後,進入src文件 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...