Sequelize ORM - 不包括 Left Join

Sequelize ORM - excluding Left Join

我正在使用 Sequelize ORM 构建 Full Stack 社交媒体应用程序。

sequelize: 6.6.5 
sequelize-cli: 6.2.0

我的数据库由 tables Users、Posts 和 ReadPosts 构建 - 它有两个外键 - UserId 和 PostId。

该应用程序的一个特点是,用户可以轻松看到 post 尚未被 him/her 阅读的新内容,因此每次用户阅读 post 它在 ReadPost table 中生成一行,由 UserId(读取 post)和 PostId(由用户读取)组成。

我现在要做的是显示所有尚未阅读的 posts,所以这将是某种排除左连接,这将获得所有现有的 posts,并使用给定的 userId 从 ReadPost 中排除那些罐子,但我不知道如何使用 Sequlize 来做到这一点。

阅读Post型号:

module.exports = (sequelize) => {
    const readPost = sequelize.define("ReadPost", {})

    readPost.associate = models => {
        readPost.belongsTo(models.User, {
            foreignKey: {
                allowNull: false
            },
            onDelete: "CASCADE",
            foreignKeyConstrains: true
        })
        readPost.belongsTo(models.Post, {
            foreignKey: {
                allowNull: false
            },
            onDelete: "CASCADE",
            foreignKeyConstrains: true
        })
    }
    return readPost
}

我知道我可以虚拟地做到这一点,只需 运行 在 posts 上找到所有(),而不显示那些尚未阅读的内容,这取决于一些 javascript 标志或简单地 class,但这是我投资组合的一个项目,所以我想正确地完成它。我能帮忙吗?

@阿纳托利

我不得不尝试一下你的代码,因为我使用的是更新版本的 sequelize 并且得到了这样的东西:

 exports.showAllUnreadPosts = (req, res, next) => {
    db.Post.findAll({
        where: {
            "ReadPost.id": null,
            userId: res.locals.userId //userId extracted from authorization middleware
        },
        include: [{
            model: db.ReadPost,
            required: false,
            attributes: []
        }]
    }) 

它会返回

"error": "Error SequelizeDatabaseError: Unknown column 'Post.ReadPost.id' in 'where clause'"

我试图理解“ReadPost.id”行:null',但据我了解 sql 语法,它将在 Post table?我没有这样的专栏,关系存在于 ReadPost table 中,它收集 userIds 和 postIds,不确定我的实现是否清晰

总而言之 - 我需要从 Post table 中获取所有现有的 posts 并将其与 ReadPost table 进行比较,其中 post存储Id和userId。所以可能我必须 运行 在 Posts 上找到所有,在 ReadPost 上用当前用户 ID 找到所有,并排除所有记录在 Read[=62= 中的那些 postId ] 来自 Post.findAll

查看那些 table 中当前数据的截图: picture of DB tables

所以基本上我需要 Post.findAll() + ReadPost.findAll() where userId: res.locals.userId and return all posts from Post table 但不存在该 ReadPost 查询。

我希望这样更清楚。

@Anatoly 11/03/22 查询现在有效,但是 returns 只有 posts 没有被任何用户读取(行不存在)并且用户是 post.[=16 的作者=]

我现在设法做的是获取用户已阅读的所有 post(代码如下)。我需要它的对立面(行不存在或存在,但不使用此 userId)

因此,从存在的所有 post 中,Select 那些被用户读取的,并从数据库中的所有 post 中排除其他那些

exports.showAllUnreadPosts = (req, res, next) => {
    db.Post.findAll({
        where: {
            '$readposts.UserId$': res.locals.userId // User Id extracted from auth middleware
        },
        include: [{
            model: db.ReadPost,
            required: false,
            attributes: [],
        }]
    }).then(unreadPosts => {
        res.status(200).json(unreadPosts);
    })
        .catch((error) => {
            res.status(500).json({
                error: 'Error ' + error
            })
        })
}

能否请教一下?

您可以通过添加条件 Readpost.id is null 查询所有在 ReadPost 中没有 link 记录的帖子,如下所示:

const unreadPosts = await Post.findAll({
  where: {
    '$ReadPost.id$': null,
    userId: userId
  },
  include: [{
    model: ReadPost,
    required: false,
    attributes: [],
    where: {
      UserId: userId
    },
  }]
})

当然,您需要添加从 PostReadPost 的关联:

Post.hasMany(ReadPost, <some_options_here>);

是的,看来我在@Anatoly 的大力帮助下找到了解决方案。

我不确定这是否是个好主意,因为我在 THEN 块中添加了第二种方法,我很高兴收到任何反馈。

exports.showAllUnreadPosts = (req, res, next) => {
    db.Post.findAll({
        where: {
            '$readposts.UserId$': res.locals.userId // User Id extracted from auth middleware
        },
        attributes: ['id'],
        include: [{
            model: db.ReadPost,
            required: false,
            attributes: [],
        }]
    }).then(readPosts => {
        db.Post.findAll({
            where: {
                id: {
                    [Op.not]: (() => readPosts.map(readPost => readPost.id))()
                }
            }
        })
            .then((unreadPosts) => {
                res.status(200).json(unreadPosts);
            })
            .catch((error) => {
                res.status(500).json({
                    error: 'Error' + error
                })
            })

    })
        .catch((error) => {
            res.status(500).json({
                error: 'Error ' + error
            })
        })
}

首先有一个方法,在readposttable和returns[=中检查所有已经被用户读过的post 18=] ID。其次在 THEN 块中,它获取数据库中所有现有的 posts,并从上述方法中排除具有 id 的那些(通过 [OP.not])。我希望它有意义,但不确定性能。