具有动态参考的Mongoose Activity模型

时间:2013-10-28 23:31:38

标签: node.js mongodb mongoose

我想创建一个活动模型,以便在我的应用程序中显示时间轴类型,但我不知道如何动态引用mongoose模式中的集合。我正在使用猫鼬(3.6.20)

到目前为止,演员总是一个用户,但_object可以是用户或帖子。

这就是我所拥有的:

userSchema = new Schema({
    _id: ObjectId;
    name: String
});

postSchema = new Schema({
    _id: ObjectId;
    author_id: String, ref: User
});

我想做的是:

activitySchema = new Schema({
    _object: { String: Id of the thing, ref:'can be user or post'} // Object that the verb occurred on... can be a post or a user
    actor: { type: String, ref: 'User' },
    action: { type: String, default: ""}, //ex: has replied to:, or started following:
});

如果可能的话,如何使用带有mongoose的动态引用来解决这个问题,我将如何填充它?

谢谢!

4 个答案:

答案 0 :(得分:16)

2017年更新..

现在可以使用refPath或甚至多个动态引用来动态引用。

    var userSchema = new Schema({
    name: String,
    connections: [{
        kind: String,
        item: { type: ObjectId, refPath: 'connections.kind' }
        }]
    }); 
  

上面的refPath属性意味着mongoose将查看connections.kind路径以确定用于populate()的模型。换句话说,refPath属性使您可以使ref属性动态化。

http://mongoosejs.com/docs/populate.html 动态参考

答案 1 :(得分:10)

如果您希望不存在可能存储在_object中的每种模型类型的多个属性,那么这是一种如何定义模式的模式:

var UserSchema = new Schema({
    name: String
});

var PostSchema = new Schema({
    author: { type: Schema.Types.ObjectId, ref: 'User' }
});

var ActivitySchema = new Schema({
    _object : Schema.Types.ObjectId,
    actor: { type: Schema.Types.ObjectId, ref: 'User' },
    action: { type: String, default: "" }
});

var models = {
    User : mongoose.model('User', UserSchema),
    Post : mongoose.model('Post', PostSchema),
    Activity : mongoose.model('Activity', ActivitySchema)
};
  1. 创建UserSchema。您不需要定义_id字段,因为它是ObjectId为您自动创建的。
  2. 使用PostSchema定义User并引用ref个实例。 typeObjectId(默认情况下定义模型 _ id`s的方式)。
  3. 定义ActivitySchema。在这种情况下,请勿定义ref类型,因为它未知。只需存储核心ObjectId类型。
  4. 当您想要创建Activity个实例时,它没有太大区别:

    var activity = new models.Activity( {
       _object: post._id,
       actor: user._id,
       action: "post"
    });
    

    无论如何,您总是使用model._id语法。

    此外,如果您知道对象的类型,则可以使用populate。例如,post行动可能意味着_object包含User

    models.Activity.find({action: 'post'}).populate({
       path: '_object'
       , select: 'name'
       , model: 'User'
    }).exec(function (err, activities) {
       console.log(activities);
    })
    

答案 2 :(得分:5)

为什么acitivitySchema没有两者兼而有之?

activitySchema = new Schema({
    user:{ type:ObjectId, ref:'User' }, 
    post:{ type:ObjectId, ref:'Post' }, 
    actor: { type: String, ref: 'User' },
    action: { type: String, default: ""}, //ex: has replied to:, or started following:
});

当您获得猫鼬对象时,只需调用populate('user')并填充('post')。它将根据保存的内容填充用户或帖子。 Mongodb非常有效率。

答案 3 :(得分:2)

如果你想让mongoose populate工作,而且架构变量数量有限,你需要做一个“稀疏模型”:

activitySchema = new Schema({
    user: {type: ObjectId, ref: 'User'},
    post: {type: ObjectId, ref: 'Post'}
    actor: { type: String, ref: 'User' },
    action: { type: String, default: ""}, //ex: has replied to:, or started following:
});

这样可以正常工作,您只需编写代码即可了解其中一个将为null。由于其他风格与查询不匹配,因此查询这些风格也非常容易。

但是,否则,您不能使用mongoose populate,但是,在您的活动架构中粘贴modelIdmodelName,然后加载相应的模型文档大约为3行代码,所以如果你真的喜欢使用可以引用不同集合的单个字段,那么不要冒汗写点什么。