2017-07-06 20 views
-1

所以我有兩個模式,文章和事件 都有一個圖像字段。如何使用不同類型的引用和填充

對於第二條,

featured_image: { 
    type: String, 
    default: '', 
} 

事件,

featured_image: { 
    type: Schema.ObjectId, 
    ref: 'Medium' 
} 

我有另一種模式,卡,這樣

type: { 
    type: String, 
    enum: ['Article', 'Event'] 
}, 
data: { 
    type: Schema.ObjectId, 
    refPath: 'type'  
} 

我試圖填充卡,這樣

Card 
    .find(query) 
    .populate({ 
      path: 'data', 
      populate: [{ 
       path: 'featured_image', 
       model: 'Medium', 
       select: 'source type' 
      }] 
    };) 

但是,它不斷給我一個轉換錯誤,因爲當卡類型爲Event時,它填充的很好,但是當它是'Article'類型時,featured_image字段是字符串類型的,因此不能填充。

如何僅在卡類型爲Event的情況下填充featured_image字段,或者它是參考ID而不是字符串。

+0

樣本輸出是否有東西,你相信沒有解決您的問題提供答案嗎?如果是這樣,請評論答案以澄清究竟需要解決的問題。如果它確實回答了你問的問題,那麼請注意[接受你的答案](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work)給你的問題問 –

+0

「凹凸」。仍然沒有迴應? –

回答

0

而不是你正在嘗試做什麼你應該使用「鑑別器」,這實際上是正確的方式來處理對象類型在給定的參考中變化的關係。

const contentSchema = new Schema({ 
    name: String 
}); 

const articleSchema = new Schema({ 
    image: String, 
}); 

const eventSchema = new Schema({ 
    image: { type: Schema.Types.ObjectId, ref: 'Medium' } 
}); 

const cardSchema = new Schema({ 
    name: String, 
    data: { type: Schema.Types.ObjectId, ref: 'Content' } 
}); 

const Medium = mongoose.model('Medium', mediumSchema); 
const Card = mongoose.model('Card', cardSchema) 

const Content = mongoose.model('Content', contentSchema); 
const Article = Content.discriminator('Article', articleSchema); 
const Event = Content.discriminator('Event', eventSchema); 

因此,你定義一個「示範基地」,如:

您可以通過在您定義的模型,它不是從「基本模式」和模式構建在不同的方式使用鑑別Content這裏你實際上指的是Event

下一部分是通過基本模型中的.discriminator()方法實際註冊到此模型的不同模式,而不是.model()方法。這用一般的Content模型註冊模式,以便當您參考使用.discriminator()定義的任何模型實例時,使用註冊的模型名稱暗示該數據中存在特殊的__t字段。

除了在不同類型上啓用貓鼬到.populate()之外,這也具有作爲附加到不同類型的項目的「完整模式」的優點。所以,如果你喜歡,你也有不同的驗證和其他方法。在數據庫上下文中的工作確實是「多態」,並附帶有有用的模式對象。

因此,我們可以演示已完成的各種「連接」,以及您現在可以使用單個模型的ArticleEvent,這些模型僅處理所有查詢和操作中的項目。並且,您不僅可以使用「單獨」,但由於其機制實際上將數據存儲在同一個集合中,因此還有一個可訪問這兩種類型的Content模型。實質上,主要關係如何在定義到Event模式中起作用。

作爲全面上市

const async = require('async'), 
     mongoose = require('mongoose'), 
     Schema = mongoose.Schema; 

mongoose.set('debug',true); 
mongoose.Promise = global.Promise; 

mongoose.connect('mongodb://localhost/cards'); 

const mediumSchema = new Schema({ 
    title: String 
}); 

const contentSchema = new Schema({ 
    name: String 
}); 

const articleSchema = new Schema({ 
    image: String, 
}); 

const eventSchema = new Schema({ 
    image: { type: Schema.Types.ObjectId, ref: 'Medium' } 
}); 

const cardSchema = new Schema({ 
    name: String, 
    data: { type: Schema.Types.ObjectId, ref: 'Content' } 
}); 

const Medium = mongoose.model('Medium', mediumSchema); 
const Card = mongoose.model('Card', cardSchema) 

const Content = mongoose.model('Content', contentSchema); 
const Article = Content.discriminator('Article', articleSchema); 
const Event = Content.discriminator('Event', eventSchema); 

function log(data) { 
    console.log(JSON.stringify(data, undefined, 2)) 
} 

async.series(
    [ 
    // Clean data 
    (callback) => 
     async.each(mongoose.models,(model,callback) => 
     model.remove({},callback),callback), 

    // Insert some data 
    (callback) => 
     async.waterfall(
     [ 
      (callback) => 
      Medium.create({ title: 'An Image' },callback), 

      (medium,callback) => 
      Content.create(
       [ 
       { name: "An Event", image: medium, __t: 'Event' }, 
       { name: "An Article", image: "A String", __t: 'Article' } 
       ], 
       callback 
      ), 

      (content,callback) => 
      Card.create(
       [ 
       { name: 'Card 1', data: content[0] }, 
       { name: 'Card 2', data: content[1] } 
       ], 
       callback 
      ) 
     ], 
     callback 
    ), 

    // Query and populate 
    (callback) => 
     Card.find() 
     .populate({ 
      path: 'data', 
      populate: [{ 
      path: 'image' 
      }] 
     }) 
     .exec((err,cards) => { 
     if (err) callback(err); 
     log(cards); 
     callback(); 
     }), 

    // Query on the model for the discriminator 
    (callback) => 
     Article.findOne({},(err,article) => { 
     if (err) callback(err); 
     log(article); 
     callback(); 
     }), 

    // Query on the general Content model 
    (callback) => 
     Content.find({},(err,contents) => { 
     if (err) callback(err); 
     log(contents); 
     callback(); 
     }), 


    ], 
    (err) => { 
    if (err) throw err; 
    mongoose.disconnect(); 
    } 
); 

而對於不同的查詢

Mongoose: cards.find({}, { fields: {} }) 
Mongoose: contents.find({ _id: { '$in': [ ObjectId("595ef117175f6850dcf657d7"), ObjectId("595ef117175f6850dcf657d6") ] } }, { fields: {} }) 
Mongoose: media.find({ _id: { '$in': [ ObjectId("595ef117175f6850dcf657d5") ] } }, { fields: {} }) 
[ 
    { 
    "_id": "595ef117175f6850dcf657d9", 
    "name": "Card 2", 
    "data": { 
     "_id": "595ef117175f6850dcf657d7", 
     "name": "An Article", 
     "image": "A String", 
     "__v": 0, 
     "__t": "Article" 
    }, 
    "__v": 0 
    }, 
    { 
    "_id": "595ef117175f6850dcf657d8", 
    "name": "Card 1", 
    "data": { 
     "_id": "595ef117175f6850dcf657d6", 
     "name": "An Event", 
     "image": { 
     "_id": "595ef117175f6850dcf657d5", 
     "title": "An Image", 
     "__v": 0 
     }, 
     "__v": 0, 
     "__t": "Event" 
    }, 
    "__v": 0 
    } 
] 
Mongoose: contents.findOne({ __t: 'Article' }, { fields: {} }) 
{ 
    "_id": "595ef117175f6850dcf657d7", 
    "name": "An Article", 
    "image": "A String", 
    "__v": 0, 
    "__t": "Article" 
} 
Mongoose: contents.find({}, { fields: {} }) 
[ 
    { 
    "_id": "595ef117175f6850dcf657d6", 
    "name": "An Event", 
    "image": "595ef117175f6850dcf657d5", 
    "__v": 0, 
    "__t": "Event" 
    }, 
    { 
    "_id": "595ef117175f6850dcf657d7", 
    "name": "An Article", 
    "image": "A String", 
    "__v": 0, 
    "__t": "Article" 
    } 
] 
相關問題