雖然,在NoSQL類的數據庫,例如MongoDB中是不存儲關係數據的,但是我們可以在應用層進行存儲。
Mongoose提供了這一特性,名爲population。
他允許我們使用不同的集合來填充文檔的特定部分。
假設我們有posts和users兩個集合
我們可以在user的原型中引用posts:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var userSchema = Schema({
_id: Number,
name: String,
posts: [{type: Schema.Types.ObjectId, ref: 'Post'}]
});
var postSchema = Schema({
_creator: {type: Number, ref: 'User'},
title: String,
text: String
});
var Post = mongoose.model('Post', postSchema);
var User = mongoose.model('User', userSchema);
User.findOne({nema: /lijian/i})
.populate('posts')
.exec(function(err, user){
if(err) return handleError(err);
console.log('The user has % post(s)', user.posts.length);
})
注:ObjectId、Number、String和Buffer都是可以直接引用的合法數據類型
在上面的查詢中,我們使用了正則表達式(RegExp)
雖然Mongoose並不包含這一特性,但實際上,原生的驅動以及其他封裝庫,就連mongo控制檯都是支持正則表達式的。
語法與標準的JavaScript/Node.js正則表達式是一樣的。
用這種方法,我們完成了對Post和User的聯合查詢。
當然也可以只返回複雜結果的一部分,例如,我們可以限制posts只取前10個:
.populate({
path: 'posts',
options: {limit:10, sort:'title'}
})
有時候,只返回文檔的特定部分比返回整個文檔更實用。
可以使用以下查詢語句實現:
.populate({
path: 'posts',
select: 'title',
options: {limit: 10, sort: 'title'}
})
此外,Mongoose可以使用查詢語句對複雜的返回結果進行過濾!
如:我們可以對text(其中一個查詢匹配的屬性)使用正則表達式匹配出“node.js”:
.populate({
path: 'posts',
select: '_id title text',
match: {text: /node\.js/i},
options: {limit:10, sort:'_id'}
})
這裏,可以按照需求定製查詢,帶上需要選擇的字段(選擇字段名字爲_id、title、text)即可。
最好的做法是隻查詢所需的部分,因爲這可以避免潛在的安全信息泄露以及減少服務器負擔。
populate 方法也能作用於文檔的複合查詢中,比如,我們可以用find方法代替findOne方法:
User.find({}, {limit:10, sort:{_id:-1}})
.populate('posts')
.exec(function(err, user){
if(err) return handleError(err);
console.log('The user has % post(s)', user.posts.length);
})
小貼士:對於自定義排序,我們可以使用形如name:-1或者name:1這樣的參數,並將他傳遞給sort字段即可。
同之前提到的一樣,這是一個MongoDB的標準接口,不適用於Mongoose