MongoDB系列8:MongoDB集合的增量更新

鄧開表同學實戰MongoDB系列文章,非常不錯,贊!大力推薦!

本文是第8篇,主要講述MongoDB集合的增量更新的實戰經驗,非常值得一看。

前面系列文章:

MongoDB安全實戰之Kerberos認證

MongoDB Compass--MongoDB DBA必備的管理工具

MongoDB安全實戰之審計

MongoDB安全實戰之SSL協議加密

MongoDB安全實戰之網絡安全加固

MongoDB索引的介紹

MongoDB存儲引擎



在關係型數據庫中,經常會遇到這樣的場景:用某張表或是多張表的關聯產生的結果集,然後持續地更新另外一張表的數據,有時為了方便,只更新變化的數據,即增量更新。那麼在MongoDB中如何實現這種場景呢?

1、現有student集合,數據如下(s_id--學號,c_id--課程號,name--姓名,sex---性別,score--成績):

MongoDB系列8:MongoDB集合的增量更新

圖1

場景一:將student集合數據複製到另外一個集合target裡面,在關係型數據庫中,複製一張表的數據可以採用insert into table_a select .....或create table table_aas select .....方式,而在MongoDB中,可以使用如下語句實現:

db.student.find().forEach( function(m) {

db.target.insert(m);

});

MongoDB系列8:MongoDB集合的增量更新

場景二:現在student集合和target集合有一樣的數據,後續如果student集合的數據有變化,target集合需要根據student集合的數據進行更新,而且每次只需要更新變化的數據,即增量更新。使用以下的語句來是實現集合的增量更新:

1)先向student集合新增一個文檔和修改s_id學號為001的文檔:

db.student.insert({"_id":15,"s_id":"006","c_id":7,"name":"ken","sex":"male","score":67})

db.student.update({"s_id":"001"},{"$set":{"sex":"female"}},false,true)

MongoDB系列8:MongoDB集合的增量更新

2) 更新集合target的數據:

db.student.find().forEach(function(m){

db.target.findAndModify({

query: { _id : m._id },

update: {Sset : {“s_id”:m.s_id, ”c_id”:m.c_id,”name”:m.name,”sex”:m.sex,”score”:m.score}},

upsert: true

});

});

MongoDB系列8:MongoDB集合的增量更新

說明:

query:對應是查詢文檔,用於檢索文檔的條件;

update: 對應修改器的文檔,用於更新所找到的文檔;

upsert: 指當沒有文檔匹配時,是否插入;

場景三:多集合關聯增量更新另一個集合。

集合student:s_id--學號,c_id--課程號,name--姓名,sex--性別,score--成績

集合course:_id--課程號,c_name--課程名稱

student和course集合數據分別如下圖:

MongoDB系列8:MongoDB集合的增量更新

圖5

MongoDB系列8:MongoDB集合的增量更新

圖6

1) 現需要查詢出成績合格(大於等於60分),的學生號、學生姓名和課程名稱。代碼如下:

db.student.aggregate([{

$lookup:

{

from :"course",

localField:"c_id",

foreignField: "_id",

as:"course_documents"

}

},

{

$replaceRoot:{newRoot: {$mergeObjects: [{ $arrayElemAt:["$course_documents",0]},"$$ROOT"] }}

},

{$project:{course_documents:0}},

{$match : {"score":{"$gte":60}}}

]).forEach(function(m) {

db.pass.insert({"_id":m._id,"s_id":m.s_id,"name":m.name,"c_name":m.c_name});

});

MongoDB系列8:MongoDB集合的增量更新

圖7

說明:

$lookup相當於關係型數據庫SQL的join。

其中from參數指定要關聯集合B;

localField參數指定集合A的等值對比的鍵。

foreignField參數指定集合B要與集合A做等值對比的鍵。

as參數指定符合關聯的集合B記錄,以指定名稱作為鍵,集合B記錄為值的數組形式返回。

$replcaceRoot作用是指定文檔提升到頂層,由於$lookup關聯後,集合B的記錄是作為as參數指定名稱的鍵的值,和集合A的字段不在同個層級,可以使用$replaceRoot實現文檔提升到頂層。

$project作用是指定的鍵是否排除,0表示排除,1表示保留。

$match相當於關係型數據庫SQL的where子句。

2) 當student和course集合數據增加時,增量更新pass集合。

分別向student、course添加兩個文檔:

db.student.insert({"_id":16,"s_id":"007","c_id":11,"name":"tony","sex":"male","score":57})

db.student.insert({"_id":17,"s_id":"007","c_id":12,"name":"tony","sex":"male","score":67})

db.course.insert({"_id":11,"c_name":"Spark"})

db.course.insert({"_id":12,"c_name":"Hbase"})

增量更新pass:

db.student.aggregate([{

$lookup:

{

from :"course",

localField:"c_id",

foreignField:"_id",

as:"course_documents"

}

},

{

$replaceRoot:{newRoot: {$mergeObjects: [{ $arrayElemAt:["$course_documents",0]},"$$ROOT"] }}

},

{$project:{course_documents:0}},

{$match : {"score":{"$gte":60}}}

]).forEach(function(m) {

db.pass.findAndModify({

query:{_id:m._id},

update:{$set :{"s_id":m.s_id,"name":m.name,"c_name":m.c_name}},

upsert:true

});

});

MongoDB系列8:MongoDB集合的增量更新

圖8

小結:

使用慣關係型數據庫後,對於轉用No-SQL數據庫的人,許多場景在關係型數據庫中實現方式,在No-SQL數據庫不一定可用。本文講述了增量更新場景在MongoDB中的實現,希望對大家有幫助。


分享到:


相關文章: