插入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":"