7

我想创建一个活动模型,以便在我的应用程序中显示时间线类型的东西,但我不知道如何在猫鼬模式中动态引用集合。我使用猫鼬(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:
});

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

谢谢!

4

4 回答 4

27

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 动态引用

于 2017-06-16T05:07:06.110 回答
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。这type是一个(这是默认定义ObjectId模型_id的方式)。
  3. 定义ActivitySchema. 在这种情况下,不要定义ref类型,因为它是未知的。只需存储核心ObjectId类型。

当你想创建一个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);
})
于 2013-10-29T00:30:36.713 回答
6

为什么 ActivitySchema 不能两者兼得?

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

当你得到 mongoose 对象时,只需调用 populate('user') 和 populate('post')。它将根据保存的内容填充用户或帖子。Mongodb 在这方面非常高效。

于 2013-10-29T00:33:00.897 回答
2

如果你想让猫鼬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:
});

这样可以正常工作,您只需编写代码即可了解其中 1 个将为空。仅查询其中一种风味也很容易,因为其他风味与查询不匹配。

但除此之外,您不能使用 mongoose populate,但是,坚持modelIdmodelName在您的活动模式中然后加载相应的模型文档大约需要 3 行代码,所以如果您真的喜欢使用可以引用不同集合的单个字段。

于 2013-10-29T00:35:03.643 回答