第7章-使用ORM類庫Mongoose提升你的Node.js數據-7.6.使用population建立關係和連接

雖然,在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

發佈了305 篇原創文章 · 獲贊 5 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章