mongodb更新文檔分為兩大類:
-
文檔替換,使用新文檔完全替換掉舊文檔
-
修改器,修改部分文檔
文檔替換
使用文檔替換非常的簡單,下面來看演示:
立即學習“PHP免費學習筆記(深入)”;
$collect->insertOne(['name'?=>?'lakers',?'nums'=>?16]); $collect->replaceOne( ????['name'=>'lakers'],? ????['name'?=>?'heat',?'nums'=>3] );
使用修改器可以完成更復雜的更新操作,比如修改、增加或刪除鍵。
“$set”修改器
“$set”用來指定一個字段的值。如果這個字段不存在,則創建它。
$collect->insertOne([ ????'name'?=>?'james', ????'age'?=>?35, ]); $collect->updateOne(['name'=>'james'], ????['$set'?=>?['fruit'?=>?'apple']] ); //?fruit字段不存在,則會創建該字段
如果現在不喜歡apple,想換成草莓
$collect->updateOne(['name'=>'james'], ????['$set'?=>?['fruit'?=>?'strawberry']] );
“$set”還可以修改鍵的類型。
#?不止喜歡草莓,還喜歡梨子、香蕉。 $collect->updateOne(['name'=>'james'], ????['$set'?=> ????????['fruit'?=>? ????????????['strawberry',?'banana',?'pear']? ????????] ????] );
“$set”也可以修改內嵌文檔
$collect->insertOne([ ????'name'?=>?'james', ????'age'?=>?35, ????'brothers'?=>?['name'?=>?'wade',?'age'=>?38] ]); $collect->updateOne(['name'=>'james'], ????['$set'?=> ????????['brothers.name'?=>?'paul'] ????] );
“$unset”修改器
使用”$unset”修改器可以刪除指定字段
$collect->updateOne(['name'=>'james'], ????['$unset'?=> ????????['brothers'?=>?''] ????] );
“$inc”修改器,增加或減少數值
和”$set”修改器一樣,如果該字段不存在則自動創建。注意:該字段值只可以是數字。
$collect->updateOne(['name'=>'james'], ????['$inc'?=> ????????['scores'?=>?61] ????] ); ##?現有積分61
現在,有獲得了10點積分。
$collect->updateOne(['name'=>'james'], ????['$inc'?=> ????????['scores'?=>?10] ????] ); ##?現有積分71
后來,用掉了50積分
$collect->updateOne(['name'=>'james'], ?????['$inc'?=>['scores'?=>?-50] ?]?);? ?##?現有積分21
數組修改器
mongodb針對數組提供了專門的修改方法。
“$push”添加元素
“$push”可以往數組里添加元素,如果該數組不存在,則會自動創建數組。現在有一個文檔用于保存文章數據:
$collect->insertOne([ ?????'_id'?=>?1,?????? ?????'title'=>'study?mongodb',?????? ?????'create_time'?=>?'2020-08-24?12?:31'? ]);? $push?=?['$push'?=>?['comments'?=>?'comments1']?];? $collect->updateOne(['_id'?=>?1?],?$push);
“$each”添加多個元素
‘$push’可以一次數組元素,如果想一次添加多個元素的話,則需要搭配使用’$each’。
$push?=?[???? ?????'$push'?=>? ?????????['comments'?=>? ?????????????['$each'?=>?['comment1',?'comment2',?'comment3']] ?????????]? ??????];? $collect->updateOne(['_id'?=>?1?],?$push);
“$slice”保留n個元素
‘$push’和’$slicet’配合使用,保留最新的n條數據,’$slice’的值只能是負整數。比如,我只想保留最新的3條評論:
#?目前數據如下 ?>?db.users.find()? {?"_id"?:?1,?"title"?:?"study?mongodb",?"create_time"?:?"2020-08-24?12:31",?"comment"?:?[?"comment1",?"comment2",?"comment3",?"comment4",?"comment5",?"comment6"?]?}
$push?=?[ ?????'$push'?=>?[? ????????'comment'?=>?[? ????????????'$each'?=>?['comment7',?'comment8',?'comment9'],????????????????????????????????'$slice'?=>?-3? ????????], ?????],? ];? $collect->updateOne(['_id'?=>?1?],?$push);
#?現數據如下? db.users.find()? {?"_id"?:?1,?"title"?:?"study?mongodb",?"create_time"?:?"2020-08-24?12:31",?"comment"?:?[?"comment7",?"comment8",?"comment9"?]?}
“$sort”排序
還可以配合’$sort’使用,保留點贊數最多的3條評論。
#?目前是集合內是空的,么有任何文檔 $collect->insertOne(['_id'?=>?1,?'title'=>'study?mongodb',?'create_time'?=>?'2020-08-24?12:31']); $push?=?[ ????'$push'?=>?[ ????????'comment'?=>?[ ????????????'$each'?=>?[ ????????????????['comment'?=>?'php',?'like'?=>?100],? ????????????????['comment'?=>?'mysql',?'like'?=>?10],? ????????????????['comment'?=>?'linux',?'like'?=>?200],? ????????????????['comment'?=>?'java',?'like'?=>?1000],? ????????????????['comment'?=>?'nginx',?'like'?=>?300],? ????????????????['comment'?=>?'composer',?'like'?=>?500],? ????????????], ????????????'$slice'?=>?-3, ????????????'$sort'?=>?['like'?=>?1] ????????], ????], ];
再來看看集合內數據是怎樣的:
>?db.users.find() {?"_id"?:?1,?"title"?:?"study?mongodb",?"create_time"?:?"2020-08-24?12:31",?"comment"?:?[?{?"comment"?:?"nginx",?"like"?:?300?},?{?"comment"?:?"composer",?"like"?:?500?},?{?"comment"?:?"java",?"like"?:?1000?}?]?}
注意不能只將 “$slice” 或者 “$sort” 與 “$push” 配合使用,且必須使用 “$each”。
“$addToSet”避免插入重復數據
使用”$addToSet”新增數組元素時,可以避免添加重復數據,比如
$collect->insertOne([ ????'_id'?=>?1, ????'name'?=>?'gwx',? ????'age'?=>?30,? ????'fruits'?=>?['apple',?'pear'] ]); $update?=?[ ????'$addToSet'?=>?[ ????????'fruits'?=>?'apple' ????] ];
上面的修改不會成功,因為apple已經存在。’$addToSet’也可以和”$each”配合使用,插入多個數組元素。
$update?=?[ ????'$addToSet'?=>?[ ????????'fruits'?=>?[ ????????????'$each'?=>?['apple',?'banana',?'orange'] ????????] ????] ]; $collect->updateOne(['_id'?=>?1],?$update);
刪除元素
可以通過”$pop”,刪除最左端或最右端的元素。
$collect->insertOne([ ????'_id'?=>?1, ????'name'?=>?'gwx',? ????'age'?=>?30,? ????'fruits'?=>?['apple',?'pear'] ]); #從數組末刪除1個元素 $update?=?[ ????'$pop'?=>?[ ????????'fruits'?=>?1 ????] ]; $collect->updateOne(['_id'?=>?1],?$update); #?從數組頭刪除一個元素 $update?=?[ ????'$pop'?=>?[ ????????'fruits'?=>?-1 ????] ]; $collect->updateOne(['_id'?=>?1],?$update);
還可以通過’$pull’刪除指定的元素
$collect->insertOne([ ????'_id'?=>?1, ????'name'?=>?'gwx',? ????'age'?=>?30,? ????'fruits'?=>?['apple',?'pear',?'apple',?'banana',?'orange'] ]); #從數組末刪除 $update?=?[ ????'$pull'?=>?[ ????????'fruits'?=>?'apple' ????] ];
數組有所有apple元素都被刪除了
upsert
upsert是一種特殊的更新。但找到符合條件的集合,那么和之前的修改時一樣的。若沒有找到符合條件的集合,那么它就會以查詢條件以及修改的文檔作為一個新文檔插入到集合中。
下面,以一個我們經常碰到的場景來舉例——記錄每個ip瀏覽的次數。若是新的ip,則新增到集合中,若已存在,就修改原有集合。
$collect->updateOne(['ip'?=>?'116.31.23.1'],?[ ????'$inc'?=>[ ????????'views'?=>?1 ????] ],?['upsert'?=>?true]); $collect->updateOne(['ip'?=>?'127.0.0.1'],?[ ????'$inc'?=>[ ????????'views'?=>?1 ????] ],?['upsert'?=>?true]); $collect->updateOne(['ip'?=>?'116.31.23.1'],?[ ????'$inc'?=>[ ????????'views'?=>?1 ????] ],?['upsert'?=>?true]);
>?db.users.find() {?"_id"?:?ObjectId("5f4336f3a95f1a505db9a2df"),?"ip"?:?"116.31.23.1",?"views"?:?2?} {?"_id"?:?ObjectId("5f4336f3a95f1a505db9a2e1"),?"ip"?:?"127.0.0.1",?"views"?:?1?}
更新多個文檔
更新多個文檔需要使用updateMany()方法,演示如下:
$collect->insertMany([ ????['name'?=>?'gwx',?'age'?=>?30], ????['name'?=>?'gwx',?'age'?=>?30], ????['name'?=>?'gwx',?'age'?=>?30], ]); $collect->updateMany([ ????'name'?=>?'gwx' ], ????['$set'?=>['age'?=>?18]] );