2017-07-05 75 views
0

文檔有2個集合電影排名電影有引用關係。這2集。查找基於一個參考家長在兒童

Movie model

var mongoose = require('mongoose'); 

var movieSchema = new mongoose.Schema({ 
    m_tmdb_id: { 
     type: Number, 
     unique: true, 
     index: true 
    }, 
    m_adult: { 
     type: Boolean 
    }, 
    m_backdrop_path: { 
     type: String, 
    }, 
    m_title: { 
     type: Number 
    }, 
    m_genres: { 
     type: Array 
    } 

}); 
var MovieModel = mongoose.model('Movie', movieSchema); 
module.exports = { 
    movie: MovieModel 
} 

Rank movie model

var mongoose = require('mongoose'); 
var rankMovieSchema = new mongoose.Schema({ 
    movie: { 
     type: mongoose.Schema.Types.ObjectId, 
     ref: 'Movie', 
     unique: true 
    }, 
    rank: { 
     type: Number 
    }, 
    count: { 
     type: Number 
    } 
}); 
var RankMovieModel = mongoose.model('RankMovie', rankMovieSchema); 
module.exports = { 
    rankmovie: RankMovieModel 
} 

我需要從集合中選擇秩電影具有特定標題[條件上的電影收藏]的所有項目。如何我可以做到這一點?

回答

1

實際上,最好的方法是使用.aggregate()$lookup在匹配條件下「加入」數據和「過濾器」。這是非常有效的,因爲MongoDB實際上在「服務器」上執行所有這些操作,而發出「多個」查詢的操作與.populate()一樣。

MovieModel.aggregate([ 
    { "$match": { "m_title": m_title } }, 
    { "$lookup": { 
    "from": RankMovieModel.collection.name, 
    "localField": "_id", 
    "foreignField": "movie", 
    "as": "rankings" 
    }} 
]) 

注:RankMovieModel.collection.name是從貓鼬註冊的Model讓「底層」集合名稱的一個很好的方式。由於該操作位於「服務器」上,因此MongoDB需要「真實集合名稱」,因此我們可以「硬編碼」或僅從模型本身上註冊的信息中獲取它。就像這裏所做的那樣。

如果有排名的「手」,那麼你最好使用$unwind,這將爲每個相關的「排行榜」項目的文件:

MovieModel.aggregate([ 
    { "$match": { "m_title": m_title } }, 
    { "$lookup": { 
    "from": RankMovieModel.collection.name, 
    "localField": "_id", 
    "foreignField": "movie", 
    "as": "rankings" 
    }}, 
    { "$unwind": "$rankings" } 
]) 

還有這裏的特殊處理MongoDB如何處理「加入」文檔以避免違反16MB BSON限制。所以其實這個特殊的事情發生時$unwind直接遵循$lookup流水線階段:

{ 
     "$lookup" : { 
      "from" : "rankmovies", 
      "as" : "rankings", 
      "localField" : "_id", 
      "foreignField" : "movie", 
      "unwinding" : { 
       "preserveNullAndEmptyArrays" : false 
      } 
     } 
    } 

所以$unwind竟「消失」,反而是「捲起」到$lookup本身彷彿這是「一個」操作。這樣我們就不會在父文檔中直接創建一個「數組」,這會導致在極端情況下超過16MB的大小與許多「相關」項目。


如果您還沒有支持$lookupMongoDB的3.2 minunum)一個MongoDB的,那麼你可以使用一個 「虛擬」 與.populate()代替(需要貓鼬4.5.0最低)。但是請注意,這實際上執行「兩節」查詢到服務器:

首先添加了「虛擬」的模式:

movieSchema.virtual("rankings",{ 
    "ref": "Movie", 
    "localField": "_id", 
    "foreignField": "movie" 
}); 

然後用.populate()發出查詢:

MovieModel.find({ "m_title": m_title }) 
    .populate('rankings') 
    .exec() 
+0

謝謝來回你的幫助。我的要求有點不同。更新了這個問題。 – Muhsin

+0

@Muhsin這非常粗魯。這個問題完全不同。你應該回到原來的問題和[問一個新的問題,而不是](https://stackoverflow.com/questions/ask)。改變你的問題不是在這裏表現的禮貌的方式。你對你實際詢問的問題有一個答案。其他任何事情都是**新問題**。很高興看到新問題,只要這個問題沒有改變。 –

+0

@Muhsin Thankyou,那更好。提示您未來的帖子。不要「隱藏」ObjectId值。特別是當您提供與「加入」相關的數據時。一旦你這樣做了,它就會使得這些值「無效」,人們不能簡單地「複製」數據,並用它來測試可能給出答案的可能解決方案。因此,確保當你提出關於該主題的問題時,使用可應用的值通過簡單的「複製/粘貼」操作,人們可以真正使用它。 –