1. 程式人生 > >MongoDB系列8:MongoDB集合的增量更新

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

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

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

前面系列文章:

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

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

640?wx_fmt=png&wxfrom=5&wx_lazy=1

1

場景一:將student集合資料複製到另外一個集合target裡面,在關係型資料庫中,複製一張表的資料可以採用insert into table_a select .....

create table table_aas select .....方式,而在MongoDB中,可以使用如下語句實現:

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

 db.target.insert(m);

});

640?wx_fmt=png

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)

640?wx_fmt=png

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

  });

});

640?wx_fmt=png

4

說明:

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

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

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

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

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

集合course_id--課程號,c_name--課程名稱

studentcourse集合資料分別如下圖:

640?wx_fmt=png

5

640?wx_fmt=png

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});

});

640?wx_fmt=png

7

說明:

$lookup相當於關係型資料庫SQLjoin

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

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

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

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

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

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

$match相當於關係型資料庫SQLwhere子句。

2) studentcourse集合資料增加時,增量更新pass集合。

分別向studentcourse新增兩個文件:

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

});

});

640?wx_fmt=png

8

小結:

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

猜你喜歡

加入技術討論群

《大資料和雲端計算技術》社群群人數已經3000+,歡迎大家加下面助手微信,拉大家進群,自由交流。

640?wx_fmt=jpeg

喜歡釘釘掃碼下面的群:

640?wx_fmt=jpeg

喜歡QQ群的,可以掃描下面二維碼:

640?wx_fmt=jpeg

歡迎大家通過二維碼打賞支援技術社群(英雄請留名,社群感謝您,打賞次數超過108+):

640?wx_fmt=jpeg