2017-07-06 59 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" 
    } 
] 
相关问题