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