【问题标题】:sequelize findAll is not checking if current user liked a postsequelize findAll 不检查当前用户是否喜欢帖子
【发布时间】:2019-11-03 10:00:53
【问题描述】:

我有一个场景,如果你喜欢一个帖子,它就会改变

liked:falseliked:true

此点赞是基于当前用户是否喜欢该帖子。问题是当新用户注册时,尽管新用户不喜欢该帖子,但它仍会显示liked 为真。

如何检查当前用户是否喜欢该帖子?就检查当前用户是否喜欢该帖子而言,我认为我的逻辑有些不正确。

我想保留findAll 功能,我应该获得所有帖子,而不仅仅是当前用户的帖子。

有点像 instagram 或 facebook。

这是帖子数组

这就是我喜欢帖子的方式

点赞帖子

likePost: async (req: any, res: Response) => {
    const created = await models.Likes.findOne({
      where: {
        userId: req.session.user.id,
        resourceId: req.params.id
      }
    });
    console.log(created);
    const post = await models.Post.findOne({ where: { id: req.params.id } });
    // if like not created then do this
    if (!created && post) {
      await models.Likes.create({
        userId: req.session.user.id,
        resourceId: req.params.id
      }).then(() => {
        post.increment("likeCounts", { by: 1 });
        post.update({ liked: req.session.user.id ? true : false });
        res.status(200).send({
          message: "You liked this post"
        });
      });
      // else if post does not exist
    } else if (!post) {
      res.status(200).send({
        message: "there is not post to be liked"
      });
    } else {
      // else if a like does exist destroy like
      await models.Likes.destroy({
        where: {
          userId: req.session.user.id
        }
      }).then(() => {
        post.decrement("likeCounts", { by: 1 });
        res.status(200).send({
          message: "You unliked this post"
        });
      });
    }

这就是我获取帖子的方式。

获取帖子

 getPosts: async (req: any, res: Response) => {
    await models.Post.findAll({
      include: [
        { model: models.User, as: "author", attributes: ["username"] },
        { model: models.Likes }
      ],
      order: [["createdAt", "DESC"]],
      limit: 6
    }).then(posts => {
      res.json(posts);
    });
  },

Post.js(模型)

"use strict";
module.exports = (sequelize, DataTypes) => {
    var Post = sequelize.define("Post", {
        title: DataTypes.STRING,
        postContent: DataTypes.STRING,
        liked: {
            type: DataTypes.BOOLEAN,
            allowNull: false,
            defaultValue: false
        },
        likeCounts: {
            type: DataTypes.INTEGER,
            allowNull: false,
            defaultValue: 0,
            validate: {
                min: 0,
            }
        },
        authorId: DataTypes.INTEGER
    }, {});
    Post.associate = function (models) {
        Post.belongsTo(models.User, {
            as: "author",
            foreignKey: "authorId",
            onDelete: "CASCADE"
        });
        Post.hasMany(models.Likes, {
            foreignKey: "resourceId",
            timestamps: false,
            targetKey: "id",
            onDelete: "CASCADE"
        });
    };
    return Post;
};

【问题讨论】:

    标签: javascript sequelize.js


    【解决方案1】:

    我相信您看到的错误是因为您没有解决返回的承诺:

        post.increment("likeCounts", { by: 1 });
        post.update({ liked: req.session.user.id ? true : false });
    

    这意味着响应将在这些查询执行之前发送。只要会话中有user.idpost.liked 的值就会设置为 true。如果后面的查询失败,您可能需要考虑使用事务来回滚一些早期的查询。我还建议使用Promise.all() 进行并发查询(它会更快)并专门使用async/await 而不要混入thenables

    likePost: async (req: any, res: Response) => {
      // fetch created and post at the same time
      const [ created, post ] = await Promise.all([
        models.Likes.findOne({
          where: {
            userId: req.session.user.id,
            resourceId: req.params.id
          }
        }),
        models.Post.findOne({
          where: {   
            id: req.params.id
          }
        }),
      ]);
    
      // no post, no updates
      if (!post) {
        return res.status(200).send({
          message: "there is no post to be liked"
        });
      }
    
      // we are going to make updates, so use a transaction, you will need to reference sequelize
      let transaction;
      try {
        transaction = await sequelize.transaction();
    
        if (!created && post) {
          // use Promise.all() for concurrency
          await Promise.all([
            models.Likes.create({
              userId: req.session.user.id,
              resourceId: req.params.id
            }, { transaction }),
            post.increment("likeCounts", { by: 1, transaction }),
            post.update({ liked: req.session.user.id ? true : false }, { transaction }),
          ]);
    
          await transaction.commit();
    
          return res.status(200).send({
            message: "You liked this post"
          });
        }
    
        await Promise.all([
          models.Likes.destroy({
            where: {
              userId: req.session.user.id
            }
          }, { transaction }),
          post.decrement("likeCounts", { by: 1, transaction }),
        ]);
    
        await transaction.commit();
    
        return res.status(200).send({
          message: "You unliked this post"
        });
      } catch (err) {
        if (transaction) {
          await transaction.rollback();
        }
        console.log('There was an error', err);
        return res.status(500);
      }
    }
    

    仅在 getPost() 上为当前用户返回 Likes

    getPosts: async (req: any, res: Response) => {
      const posts = await models.Post.findAll({
        include: [
          { model: models.User, as: "author", attributes: ["username"] },
          // limit the likes based on the logged in user
          { model: models.Likes, required: false,
            where: { userId: req.session.user.id },
          },
        ],
        order: [["createdAt", "DESC"]],
        limit: 6
      });
    
      return res.json(posts);
    },
    

    【讨论】:

    • 我会试一试这段代码,让你知道它是怎么回事。非常感谢 doublesharp 这一直困扰着我最长的时间。
    • 当帖子数组中确实存在 { error: column "likeCounts" does not exist 时,我得到了它,您知道是什么原因造成的吗?
    • 你在承诺中调用了 models.Likes.findOne 两次,那是偶然的
    • 喜欢帖子的逻辑是有效的,但是一个新用户注册并登录,它显示已被喜欢的帖子,当新用户从未喜欢过我时,你认为 getPosts应该以检查当前用户是否喜欢该帖子的方式进行修改?
    • post.liked 在所有用户之间共享,因此如果您想为每个用户设置它,您可以在模型上使用 DataType.VIRTUAL 并使用自定义 get() 来检查 this.getDataValues('likes').length 或类似于返回真/假。
    【解决方案2】:

    因此,通过@doublesharp 帮助,我能够确定当前用户是否喜欢该帖子,方法是使用 sequelize 数据类型 VIRTUAL 以及使用 getDataValue

    更新代码

    帖子(模型)

    "use strict";
    module.exports = (sequelize, DataTypes) => {
        var Post = sequelize.define("Post", {
            title: DataTypes.STRING,
            postContent: DataTypes.STRING,
            liked: {
                type: DataTypes.VIRTUAL,
                allowNull: false,
                defaultValue: false,
                get: function () {
                    return this.getDataValue('Likes').length ? true : false;
                }
            },
            likeCounts: {
                type: DataTypes.INTEGER,
                allowNull: false,
                defaultValue: 0,
                validate: {
                    min: 0,
                }
            },
            authorId: DataTypes.INTEGER
        }, {});
        Post.associate = function (models) {
            Post.belongsTo(models.User, {
                as: "author",
                foreignKey: "authorId",
                onDelete: "CASCADE"
            });
            Post.hasMany(models.Likes, {
                foreignKey: "resourceId",
                timestamps: false,
                targetKey: "id",
                onDelete: "CASCADE"
            });
        };
        return Post;
    };
    //# sourceMappingURL=post.js.map
    

    【讨论】:

      猜你喜欢
      • 2018-01-16
      • 2021-03-02
      • 1970-01-01
      • 2018-10-13
      • 2019-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多