Mongoose,在模式(枚举)中定义OR引用?

thread = new mongoose.Schema({ post: {type: Schema.Types.ObjectId, ref: 'Post'}, comment: {type: Schema.Types.ObjectId, ref: 'Comment'}, }) 

但实际上,线程只能有post或评论,不能同时拥有。

所以理想的定义应该像枚举

  thread = new mongoose.Schema({ data: {type: Schema.Types.ObjectId, ref: 'Post'} OR?? {type: Schema.Types.ObjectId, ref: 'Comment'}, }) 

我如何在Mongoose中定义这种types的东西?

或者做这种事情的正确方法是什么?

你想要的是鉴别者。 这实际上是指同一个“核心”模型,但是它是以一种特殊的方式处理的,所以不同types的对象是独特的,甚至被认为是有自己的模型。

作为使用的一个例子列表:

 var async = require('async'), util = require('util'), mongoose = require('mongoose'), Schema = mongoose.Schema; mongoose.connect('mongodb://localhost/content'); mongoose.set("debug",true); function BaseSchema() { Schema.apply(this,arguments); this.add({ "author": String, "body": String, "created": { "type": Date, "default": Date.now() } }); } util.inherits(BaseSchema,Schema); var itemSchema = new BaseSchema(); var postSchema = new BaseSchema({ "title": String, "score": Number }); var commentSchema = new BaseSchema({ "post": { "type": Schema.Types.ObjectId, "ref": "Post" } }); var Item = mongoose.model('Item',itemSchema), Post = Item.discriminator('Post',postSchema), Comment = Item.discriminator('Comment',commentSchema); async.series( [ // Clean data function(callback) { Item.remove({},callback); }, // Insert Post function(callback) { async.waterfall( [ function(callback) { Post.create({ "title": "This post", "author": "bill", "body": "Whoa!" },callback); }, function(post,callback) { Comment.create({ "author": "ted", "body": "Excellent!", "post": post },callback); } ], callback ); }, function(callback) { console.log("All Items"); Item.find().exec(function(err,docs) { console.log(docs); callback(err); }) }, function(callback) { console.log("Just populated Comments"); Comment.find().populate('post').exec(function(err,docs) { console.log(docs) callback(err); }); } ], function(err) { if (err) throw err; mongoose.disconnect(); } ); 

而输出:

 All Items Mongoose: items.find({}) { fields: undefined } [ { created: Wed Mar 16 2016 14:15:56 GMT+1100 (AEDT), __t: 'Post', __v: 0, body: 'Whoa!', author: 'bill', title: 'This post', _id: 56e8cfed833e67750b678d9c }, { created: Wed Mar 16 2016 14:15:56 GMT+1100 (AEDT), __t: 'Comment', __v: 0, post: 56e8cfed833e67750b678d9c, body: 'Excellent!', author: 'ted', _id: 56e8cfed833e67750b678d9d } ] Just populated Comments Mongoose: items.find({ __t: 'Comment' }) { fields: undefined } Mongoose: items.find({ __t: 'Post', _id: { '$in': [ ObjectId("56e8cfed833e67750b678d9c") ] } }) { fields: undefined } [ { created: Wed Mar 16 2016 14:15:56 GMT+1100 (AEDT), __t: 'Comment', __v: 0, post: { created: Wed Mar 16 2016 14:15:56 GMT+1100 (AEDT), __t: 'Post', __v: 0, body: 'Whoa!', author: 'bill', title: 'This post', _id: 56e8cfed833e67750b678d9c }, body: 'Excellent!', author: 'ted', _id: 56e8cfed833e67750b678d9d } ] 

如果你仔细看看清单,看到的是我们确实为Item创build了一个模型,这个模型将包含所有物品,但最有趣的事情发生在以下几行:

 var Item = mongoose.model('Item',itemSchema), Post = Item.discriminator('Post',postSchema), Comment = Item.discriminator('Comment',commentSchema); 

因此,我们不是使用Item.discriminator()来接下来的两个模型定义,而是调用Item.discriminator() 。 这将创build将包含在Item “特殊模型”,当然每个types都有自己的附加模式,以及与该模式相关的任何逻辑。

由于所有数据实际上都在同一个集合中,即使我们单独使用每个模型,也会看到每个对象都有一个以__t为单位的特殊键。 这包含数据实际关联的模型的注册名称。

"debug"选项设置,您可以看到mongoose实际上发出查询。 所以当你只想处理Comment__t值会自动添加到查询条件(当然还有对象的创build)。 在我们要求“注释”包含对Post的引用的同一种情况下,当查找Post模型中应该引用的内容时,将应用相同types的过滤。

这是一个非常强大的模式,也可以采用与此处所展示的相同types的inheritance,或者也可以仅使用完全空白或单独的模式定义。

如果它只是一个“参考”这个集合中的数据的领域。 然后使用外部集合中的Item的基本模型具有相同的结果。

 var otherSchema = new Schema({ "item": { "type": Schema.Types.ObjectId, "ref": "Item" } }); mongoose.model("Other",otherSchema); mongoose.model("Other").find().populate("item").exec(function(err,docs( { // populates references with either Comment or Post // as per their assigned __t value }); 

如果引用的项目是一个Comment ,那么它将获得Comment模式的所有附加好处。 或者如果它是一个Post ,那么你看到相同的第一类对象的待遇。

所以,无论你想使用它,一旦使用鉴别器定义,然后mongoose会为你解决。