如何在 Sequelize 模型上实现 'replyingTo' 和 'replies' 关联

How to implement 'replyingTo' and 'replies' associations on Sequelize model

我有一个模型正在为 post 续集。我希望您可以检索 和 post 的回复,以及 post 和 post 的回复。

理论上这只需要一个外键,一个 'replyId' 字段,所以你有 table:

----------------------
|id|post     |replyId|
----------------------
|1 |post one |null   |
|2 |replying |1      |
|3 |replying |1      |
----------------------

因此,要让 post 回复 1,您需要查找 1
中的 replyId 要获得 post 3 的回复,您需要查找 1

id

续集关系为:

Post.hasMany(models.Post, { as: 'Replies' })
Post.hasOne(models.Post, { as: 'ReplyingTo' })

然后在将 posts 添加到数据库时:

//Having created `post`
post.setReplyingTo(replyingToPost)
//Having found `replyingToPost`
replyingToPost.addReplies(post)

但无论我尝试什么,都存在某种错误,例如在上面的 table 中,它是 null 你得到 id 3 而 sequelize 没有 return id 2

的任何回复

出现此问题是因为您想在单个字段 replyId 上持有两个关联(hasManyhasOne)。我建议你只使用一个关联,第二个可以通过 instanceMethods 轻松实现。让我告诉你如何做到这一点

Post.hasMany(models.Post, { as: 'Replies', foreignKey: 'replyId' });

它在字段 replyId 上创建一个关联,因此我们现在可以轻松 get/set 指定 post 的回复。现在,为了获得在单个 post 上设置 ReplyingTo 的可能性,我们必须在 Post 模型上添加两个实例方法。

instanceMethods: {
    getReplyingTo: function(){
        return this.sequelize.models.Post.findByPrimary(this.replyId);
    },
    setReplyingTo: function(replyingToPost){
        return this.update({ replyId: replyingToPost.id });
    }
}

所以,完整的例子可能就是这样

Post.create({ post: 'post content' }).then((post) => {
    Post.create({ post: 'reply to previous' }).then((firstReply) => {
        firstReply.setReplyingTo(post).then((self) => {
            // now firstReply has replyId: 1
        });
    });
});

通过 setReplyingTo 生成的查询类似于

UPDATE "posts" SET "replyId" = 1 WHERE "id" = 2;

另一方面,我们也可以得到给定post回复

的post
firstReply.getReplyingTo().then((replyingToPost) => {
    // here we get the first created post
});

生成下面SQL

SELECT "id", "post", "replyId" FROM "posts" AS "post" WHERE "post"."id" = 1;