MongoDB系列8:MongoDB集合的增量更新
鄧開表同學實戰MongoDB系列文章,非常不錯,贊!大力推薦!
本文是第8篇,主要講述MongoDB集合的增量更新的實戰經驗,非常值得一看。
前面系列文章:
在關係型資料庫中,經常會遇到這樣的場景:用某張表或是多張表的關聯產生的結果集,然後持續地更新另外一張表的資料,有時為了方便,只更新變化的資料,即增量更新。那麼在MongoDB中如何實現這種場景呢?
1、現有student集合,資料如下(s_id--學號,c_id--課程號,name--姓名,sex---性別,score--成績):
圖1
場景一:將student集合資料複製到另外一個集合target裡面,在關係型資料庫中,複製一張表的資料可以採用insert into table_a select .....或
db.student.find().forEach( function(m) {
db.target.insert(m);
});
圖2
場景二:現在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)
圖3
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
});
});
圖4
說明:
query:對應是查詢文件,用於檢索文件的條件;
update: 對應修改器的文件,用於更新所找到的文件;
upsert: 指當沒有文件匹配時,是否插入;
場景三:多集合關聯增量更新另一個集合。
集合student:s_id--學號,c_id--課程號,name--姓名,sex--性別,score--成績
集合course:_id--課程號,c_name--課程名稱
student和course集合資料分別如下圖:
圖5
圖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});
});
圖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
});
});
圖8
小結:
使用慣關係型資料庫後,對於轉用No-SQL資料庫的人,許多場景在關係型資料庫中實現方式,在No-SQL資料庫不一定可用。本文講述了增量更新場景在MongoDB中的實現,希望對大家有幫助。
猜你喜歡
加入技術討論群
《大資料和雲端計算技術》社群群人數已經3000+,歡迎大家加下面助手微信,拉大家進群,自由交流。
喜歡釘釘掃碼下面的群:
喜歡QQ群的,可以掃描下面二維碼:
歡迎大家通過二維碼打賞支援技術社群(英雄請留名,社群感謝您,打賞次數超過108+):