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--成绩):

图1

场景一:将student集合数据复制到另外一个集合target里面,在关系型数据库中,复制一张表的数据可以采用insert into table_a select .....或create table table_aas select .....方式,而在MongoDB中,可以使用如下语句实现:

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中的实现,希望对大家有帮助。

原文发布于微信公众号 - 大数据和云计算技术(jiezhu2007)

原文发表时间:2018-04-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT大咖说

基于PG数据库插件的SQL规范审核工具

内容来源:2017 年 10 月 21 日,平安科技数据库架构师陈刚在“PostgreSQL 2017中国技术大会”进行《基于PG数据库插件的SQL规范审核工具...

1542
来自专栏知识分享

51单片机开发板(W25Q16学习)

---恢复内容开始--- 今天测试开发板的W25Q16(16Mbit--Flash)写一篇文章备忘一下 先说一下容量的单位 计算机存储单位一般用B,KB、MB、...

3474
来自专栏Golang语言社区

Go语言并发编程总结

Golang :不要通过共享内存来通信,而应该通过通信来共享内存。这句风靡在Go社区的话,说的就是 goroutine中的 channel ....... 他在...

2719
来自专栏C/C++基础

腾讯2016春季校园实习招聘技术岗初试(一面)问题汇总(CC++后台)

2016.4.11日广州参加了腾讯的CC++后台技术一面,安全技术类的面试。面试官人很温和,经历了大概70分钟的问答,特将遇到的面试问题汇总如下,自己总结学习,...

801
来自专栏程序员的知识天地

这4个Python实战项目,让你瞬间读懂Python!

Python当下真的很火。Python实战项目,也一直尤为关注,接下来,和大家介绍下十个Python练手的实战项目

1143
来自专栏沈唁志

浅谈PHP中的设计模式

1573
来自专栏Golang语言社区

Go语言并发编程总结

Golang :不要通过共享内存来通信,而应该通过通信来共享内存。这句风靡在Go社区的话,说的就是 goroutine中的 channel ....... 他在...

3077
来自专栏北京马哥教育

编写Linux Shell脚本的最佳实践

来自:Myths的个人博客 作者:myths 链接:https://blog.mythsman.com/2017/07/23/1/(点击尾部阅读原文前往) 前言...

3979
来自专栏技术博客

编写高质量代码改善C#程序的157个建议[用抛异常替代返回错误、不要在不恰当的场合下引发异常、重新引发异常时使用inner Exception]

  自从.NET出现后,关于CLR异常机制的讨论就几乎从未停止过。迄今为止,CLR异常机制让人关注最多的一点就是“效率”问题。其实,这里存在认识上的误区,因为正...

1032
来自专栏杨建荣的学习笔记

从sysbench中学习Lua

我做事喜欢结果导向,喜欢快速迭代,能10分钟搞定,绝对不愿意花15分钟。但是技术行当,还是得耐得住寂寞,因为很多事情10分钟搞不定,可能100分钟,100...

2985

扫码关注云+社区

领取腾讯云代金券