邓开表同学实战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中的实现,希望对大家有帮助。
猜你喜欢
#大数据和云计算机技术社区#博客精选(2017)
NoSQL 还是 SQL ?这一篇讲清楚
阿里的OceanBase解密
#大数据和云计算技术#: "四有"社区介绍
大数据和云计算技术周报(第33期)
新数仓系列:Hbase周边生态梳理(1)
《大数据架构详解》第2次修订说明
云观察系列:漫谈运营商公有云发展史
云观察系列:百度云的一波三折
云观察系列:阿里云战略观察
超融合方案分析系列(7)思科超融合方案分析
加入技术讨论群
《大数据和云计算技术》社区群人数已经3000+,欢迎大家加下面助手微信,拉大家进群,自由交流。
喜欢钉钉扫码下面的群:
喜欢QQ群的,可以扫描下面二维码:
欢迎大家通过二维码打赏支持技术社区(英雄请留名,社区感谢您,打赏次数超过108+):