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会为你解决。
- NodeJS + Mongoose:更新Mongoose模型的所有字段
- Mongooseembedded式文档/ DocumentsArrays ID
- 唯一索引不适用于Mongoose / MongoDB
- Monogdb崩溃使用节点js的多个连接
- 无法在node.js中用mongoose查询mongoDB
- MongoDB / Strongloop / Loopback – 带无线networking的设备之间的脱机同步无线连接
- mongoose模式检查模型实例是否第一次被保存
- 如何在Node中使用Mongoose访问`findAndModify`方法?
- Mongoose:根据ID从数组中删除对象(Cast Error)