MongoDB修改數(shù)據(jù)update和save方法
前面我簡(jiǎn)單介紹了下
MongoDB怎樣插入數(shù)據(jù).那么數(shù)據(jù)插入到數(shù)據(jù)庫(kù)中,就可能會(huì)修改數(shù)據(jù).在MongoDB中,它提供了修改數(shù)據(jù)的方法:update.下面,我來(lái)簡(jiǎn)單說(shuō)下update的使用方法.
首先,我們操作的數(shù)據(jù)都存放在test數(shù)據(jù)庫(kù)中的name集合,集合中有4條記錄如下:
> db
test
> show collections
name
system.indexes
> db.name.find()
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "xiaoqiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "dengdeng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "guage", "lname" : "zeng" }
下面我們來(lái)試著修改一下這些數(shù)據(jù).在前面的插入中,我說(shuō)過(guò),插入時(shí)可以以文檔的的方式插入,也可以先把文檔賦值給變量,再以變量的方式插入.update方法也可以用這兩種方式.我先用文檔的方式來(lái)修改集合中的第二條記錄,命令如下:
> db.name.update({"_id" : ObjectId("5059223a955cfb1fd75066cc")},{"fname" : "qiang", "lname" : "he"})
> db.name.find() #檢查發(fā)現(xiàn),數(shù)據(jù)修改過(guò)來(lái)了,和預(yù)期的結(jié)果一樣
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "qiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "dengdeng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "guage", "lname" : "zeng" }
我們?cè)儆米兞康姆绞絹?lái)修改該集合中的第三條記錄.首先將它找出來(lái)賦值給變量someone:
> someone=db.name.findOne({"_id" : ObjectId("50592245955cfb1fd75066cd")})
{
"_id" : ObjectId("50592245955cfb1fd75066cd"),
"fname" : "dengdeng",
"lname" : "pan"
}
重新賦值你要修改的內(nèi)容來(lái)修改變量someone的值:
> someone.fname="deng"
deng
用修改過(guò)的變量替換之前文檔的位置來(lái)達(dá)到修改數(shù)據(jù)的目的:
> db.name.update({"_id" : ObjectId("50592245955cfb1fd75066cd")},someone)
> db.name.find() #檢查發(fā)現(xiàn),數(shù)據(jù)修改過(guò)來(lái)了,和預(yù)期的結(jié)果一樣
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "qiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "deng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "guage", "lname" : "zeng" }
之前我說(shuō)過(guò),save函數(shù)實(shí)際就是根據(jù)參數(shù)條件,調(diào)用了insert或update函數(shù).那么save方法是否也能實(shí)現(xiàn)數(shù)據(jù)的修改操作呢?下面我們來(lái)實(shí)驗(yàn)一下.首先還是以文檔的方式來(lái)進(jìn)行修改操作:
> db.name.save({"_id" : ObjectId("50592253955cfb1fd75066ce")}, {"fname" : "dongren", "lname" : "zeng"})
> db.name.find() #檢查發(fā)現(xiàn),數(shù)據(jù)修改過(guò)來(lái)了,但和預(yù)期的結(jié)果不一樣,跟之前插入數(shù)據(jù)一樣,save方法也同樣將第二個(gè)參數(shù)"忽略"了.
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "qiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "deng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce") }
正確的操作方式如下:
> db.name.save({"_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "dongren", "lname" : "zeng"})
> db.name.find() #檢查發(fā)現(xiàn),數(shù)據(jù)修改過(guò)來(lái)了,和預(yù)期的結(jié)果一樣
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "qiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "deng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "dongren", "lname" : "zeng" }
下面使用變量的方式來(lái)修改:
> someone=db.name.findOne({"_id" : ObjectId("50592253955cfb1fd75066ce")})
{
"_id" : ObjectId("50592253955cfb1fd75066ce"),
"fname" : "dongren",
"lname" : "zeng"
}
> someone.fname="guage"
guage
> db.name.save(someone)
> db.name.find() #檢查發(fā)現(xiàn),數(shù)據(jù)修改過(guò)來(lái)了,和預(yù)期的結(jié)果一樣
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "qiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "deng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "guage", "lname" : "zeng" }
下面,我們也同樣來(lái)看看save和update這兩方法的具體實(shí)現(xiàn).首先是save方法:
> db.name.save
function (obj) {
if (obj == null || typeof obj == "undefined") {
throw "can't save a null";
}
if (typeof obj == "number" || typeof obj == "string") {
throw "can't save a number or string";
}
if (typeof obj._id == "undefined") {
obj._id = new ObjectId;
return this.insert(obj);
} else {
return this.update({_id:obj._id}, obj, true);
}
}
參數(shù)說(shuō)明:
obj:要更新的記錄,只能是單條記錄,如果collection沒(méi)有存在與obj一樣的id,則添加一條記錄,否則更新.
再來(lái)看看update方法:
> db.name.update
function (query, obj, upsert, multi) {
assert(query, "need a query");
assert(obj, "need an object");
var firstKey = null;
for (var k in obj) {
firstKey = k;
break;
}
if (firstKey != null && firstKey[0] == "$") {
this._validateObject(obj);
} else {
this._validateForStorage(obj);
}
if (typeof upsert === "object") {
assert(multi === undefined, "Fourth argument must be empty when specifying upsert and multi with an object.");
opts = upsert;
multi = opts.multi;
upsert = opts.upsert;
}
this._db._initExtraInfo();
this._mongo.update(this._fullName, query, obj, upsert ? true : false, multi ? true : false);
this._db._getExtraInfo("Updated");
}
參數(shù)說(shuō)明:
1)query:查詢(xún)條件,類(lèi)似于update語(yǔ)句內(nèi)where后面的內(nèi)容
2)obj:update的對(duì)象和一些更新的操作符(如$、$inc等),也可以理解為
關(guān)系型數(shù)據(jù)庫(kù)update語(yǔ)句內(nèi)set后面的內(nèi)容
3)upsert:如果不存在update的紀(jì)錄,是否插入obj這個(gè)新的document。true為插入,默認(rèn)是false,不插入
4)multi:默認(rèn)是false,只更新找到的第一條紀(jì)錄,如果為true,按條件查出來(lái)的多條紀(jì)錄全部更新。
update方法至少得接收兩個(gè)參數(shù):要修改的對(duì)象(query)和修改后的對(duì)象(obj),而后兩個(gè)參數(shù)它的默認(rèn)值均為false.下面我再來(lái)簡(jiǎn)單實(shí)驗(yàn)下,后兩個(gè)參數(shù)的基本用法.
首先說(shuō)說(shuō)第四個(gè)參數(shù)multi的作用:默認(rèn)是false,只更新找到的第一條紀(jì)錄,如果為true,按條件查出來(lái)的多條紀(jì)錄全部更新.
> db.name.update({fname:"jeff"},{$set:{lname:"li"}},false,false) #為了讓大家看得清楚點(diǎn),我把后兩個(gè)值都寫(xiě)了出來(lái),這里可以不用寫(xiě)的,因?yàn)槟J(rèn)均為false.這里用到了修改器$set,關(guān)于修改器我將在以后介紹
> db.name.find() #參數(shù)multi的值是false,只更新找到的第一條紀(jì)錄
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "li" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "qiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "deng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "guage", "lname" : "zeng" }
{ "_id" : ObjectId("50592ead955cfb1fd75066cf"), "fname" : "jeff", "lname" : "chen" }
{ "_id" : ObjectId("50592ecb955cfb1fd75066d0"), "fname" : "jeff", "lname" : "zhao" }
{ "_id" : ObjectId("50592edb955cfb1fd75066d1"), "fname" : "jeff", "lname" : "qian" }
> db.name.update({fname:"jeff"},{$set:{lname:"jiang"}},false,true)
> db.name.find() #參數(shù)multi的值是true,更新找到的所有紀(jì)錄
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "qiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "deng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "guage", "lname" : "zeng" }
{ "_id" : ObjectId("50592ead955cfb1fd75066cf"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("50592ecb955cfb1fd75066d0"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("50592edb955cfb1fd75066d1"), "fname" : "jeff", "lname" : "jiang" }
再來(lái)看看第三個(gè)參數(shù)upsert的作用:如果不存在update的紀(jì)錄,是否插入obj這個(gè)新的document。true為插入,默認(rèn)是false,不插入.
> db.name.update({fname:"jeffery"},{$set:{lname:"jiang"}},false,true)
> db.name.find() #參數(shù)upsert的值是false,不插入
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "qiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "deng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "guage", "lname" : "zeng" }
{ "_id" : ObjectId("50592ead955cfb1fd75066cf"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("50592ecb955cfb1fd75066d0"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("50592edb955cfb1fd75066d1"), "fname" : "jeff", "lname" : "jiang" }
> db.name.update({fname:"jeffery"},{$set:{lname:"jiang"}},true,true)
> db.name.find() #參數(shù)upsert的值是true,插入.又學(xué)到一種插入數(shù)據(jù)的方法!
{ "_id" : ObjectId("5059221f955cfb1fd75066cb"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059223a955cfb1fd75066cc"), "fname" : "qiang", "lname" : "he" }
{ "_id" : ObjectId("50592245955cfb1fd75066cd"), "fname" : "deng", "lname" : "pan" }
{ "_id" : ObjectId("50592253955cfb1fd75066ce"), "fname" : "guage", "lname" : "zeng" }
{ "_id" : ObjectId("50592ead955cfb1fd75066cf"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("50592ecb955cfb1fd75066d0"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("50592edb955cfb1fd75066d1"), "fname" : "jeff", "lname" : "jiang" }
{ "_id" : ObjectId("5059357ad3ba22406ad408e6"), "fname" : "jeffery", "lname" : "jiang" }
update方法操作其實(shí)還是有點(diǎn)復(fù)雜的,這里我只簡(jiǎn)單地介紹了下它的基體操作,復(fù)雜的操作是合理利用各種修改器,以達(dá)到更高效更方便的管理.關(guān)于修改器的使用,我將在以后實(shí)驗(yàn).