【问题标题】:Mongoose Activity model with dynamic reference具有动态参考的 Mongoose Activity 模型
【发布时间】:2019-12-13 16:53:09
【问题描述】:

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

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

谢谢!

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    2017 年更新..

    您现在可以使用 refPath 甚至多个动态 ref 来获得动态 ref。

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

    【讨论】:

    • 这一定是答案!
    • 救命稻草,上帝保佑你
    【解决方案2】:

    如果您不想为可能存储在_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 并使用ref 引用User 实例。 typeObjectId(这是 models_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);
    })
    

    【讨论】:

      【解决方案3】:

      为什么 acitivitySchema 不能两者兼得?

      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 在这方面效率极高。

      【讨论】:

        【解决方案4】:

        如果您希望 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:
        });
        

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

        但除此之外,你不能使用猫鼬populate,但是,在你的活动模式中粘贴modelIdmodelName然后加载相应的模型文档大约是3行代码,所以不要'如果您真的喜欢使用可以引用不同集合的单个字段,那么不必为此写一些东西。

        【讨论】:

        • 看起来我们俩同时回答了完全相同的问题。 :)
        • 大声笑,是的,你们俩都做了,两个答案都是正确的,但我把答案交给了@PradeepMahdevu ;) 谢谢你们俩。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-05-04
        • 1970-01-01
        • 2016-06-12
        • 2021-10-16
        • 2018-03-28
        • 1970-01-01
        • 2021-02-24
        相关资源
        最近更新 更多