mongodb相关 (population)


记录Mongodb的populate

	Mongodb是文档型数据库,不存在像关系型数据库一样的外键设置,但通过Mongodb中的populate函数可以模拟关系型数据库的外键连接后的查询功能。
	文档型数据库存储自由,不像关系型数据库在插入数据等时需要严格按照表的结构,而文档型数据库即可随意的增添属性列等。但文档型数据库在处理表间关联时较麻烦,而population就是Mongoose封装的用于在展示查询结果的视图时填充被关联的表的相关字段(前提是该字段已设置了关联其他表,且满足类型等条件,下面会讲)。
	

使用学生表,课程表,选课表记录对Mongodb中populate函数的理解


	//引入mongoose模块,用于在nodejs端操作Mongodb数据库
	var mongoose = require('mongoose');	
	
	//设置连接,其中mongdb是使用Mongodb数据库需要的协议,在IP:port/后填入的是数据库名称
	mongoose.connect('mongodb://localhost:27017/test');
	var db = mongoose.connection;
	
	//监听数据库的连接状态
	db.on('open',function() {
		console.log('数据库连接成功');
	});
	
	db.on('error',function(){
		console.log('数据库连接失败');
	});
	
	
	// 引入Schema来定义数据库中表的结构
	var Schema = mongoose.Schema;
	
	// 设置学生表的表结构
	var studentSchema = new Scheam({
		sno:String,
		sname:String
	},{
		// Mongodb中有自带的_v和_id字段,设置versionKey为false将不增添_v字段
		versionKey:false
	});
	
	// 使用mongoose.model实例出表数据的构造函数,后续的表的元祖将根据此构造函数实例对象
	var Student = mongoose.model('Student',studentSchema);
	


	// 定义课程表的结构
	var courseSchema = new Scheam({
		cno:String,
		cname:String,
	},{
		versionKey:false
	});
	
	// 定义课程表的的构造函数
	var Course = mongoose.model('Course', courseSchema);

	

	// 定义选课表的表的数据结构
	var scSchema = new Scheam({
		sno:{type:Scheam.Types.ObjectId,ref:'Student'},
		con:{type:Scheam.Types.ObjectId,ref:'Course'},
	},{
		versionKey:false
	});
	var SC = mongoose.model('SC', scSchema);
	

  在这里需要注意的就是在设置表间关联时,关联字段的类型(type)和引用(ref)需要在定义表的结构(定义某张表的Schema时就声明好)

  在Mongodb中使用类似外键的功能需要将要关联的表的类型设置为Scheam.Types.ObjectId类型。例如在SC表中的sno和cno属性是使用Student表中的sno属性列,Course表中的cno属性列。想要做到表间关联需要设置表字段的类型为Schema.Types.ObjectId类型,这点与关系型数据库相类似,关系型数据库中表间关联需要存放的别的表的主键字段,根据主键可以唯一的查询出数据库中的数据。而Mongodb中_id字段是数据库自有的,且每个元祖的_id不同,相当于主键功能,可用于唯一的查询数据,故表间关联需要设置关联字段的类型为type。

  ref设置了关联字段中引用的是哪张表,注意设置的是被引用表的mongoose.model中的第一个参数,设置了这个才能使用populate函数查询出关联的依赖项

在nodejs中操作Mongodb的增删改查

简单例子,文件目录结构如下:

	var express = require('express');
	var app = express();
	
	// 引用
	var StudentTable = require('./database').StudentTable;
	var CourseTable = require('./database').CourseTable;
	var SCTable = require('./database').SCTable;
	
	
	var student = new StudentTable({
	    sname:'黄猫',
	    sage:30,
	    sgender:1
	});
	student.save();
	
	var course = new CourseTable({
	    cname:'大数据',
	    cteacher:'嘿嘿'
	});
	course.save();
	
	StudentTable.find({sname:'白猫'},function (err, students) {
	    if (!err) {
	        CourseTable.find({cname:'Html5'},function (err,courses) {
	            var sc = new SCTable({
	                sno:students[0]._id,
	                cno:courses[0]._id
	            });
	            sc.save()
	        });
	    }
	});

通过修改上述student,course内容存入多条数据,在可视化工具Robo 3T中可以查看到如下:

1.StudentTable中

2.CourseTable中

	// 填充sc(选课表)设置第一条选课记录为Student表的第一个学生选取了Course表的第一个课程,注意这里填充的都是id
	StudentTable.find({sname:'白猫'},function (err, students) {
	    if (!err) {
	        CourseTable.find({cname:'Html5'},function (err,courses) {
	            var sc = new SCTable({
	                sno:students[0]._id,
	                cno:courses[0]._id
	            });
	            sc.save()
	        });
	    }
	});

3.SCTable中

4.查询出表间关联字段


	SCTable.find()
	// 填充sc表的sno,cno字段,执行populate的前提是这两个字段在设置表的结构(Schema)时已经设置好类型和引用的表名
    .populate('sno cno','-_id')
    .exec(function (err, data) {
        if (!err) {
        		// 这里输出全部的数据
            console.log(data);
            for (var i = 0; i < data.length; i++) {
                console.log(data[i].sno.sname);
                console.log(data[i].sno.sage);
                console.log(data[i].cno.cname);
                console.log(data[i].cno.cteacher);
            }
        }
    });
    

终端输出如下:

关于populate函数参数

Query.populate(path, [select], [model], [match], [options]) 语法

para1:(path)必填参数,指定要填充的表的字段,注意指定的是前面查询的表的字段,多个字段间使用空格隔开

para2:(select)可选参数,不写时默认填充的是被关联表的所有字段,可填入String或Object类型
String类型时‘sname -_id’ ‘-’表示不填入该字段
Object类型时{sname:1, _id:0} 1表示填充,0表示不填充

后续几个参数基本用不到


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM