【问题标题】:Has the user liked the post before or not using Sequelize用户在使用 Sequelize 之前是否喜欢过该帖子
【发布时间】:2021-03-02 12:13:31
【问题描述】:

当前,当用户喜欢某个帖子时,该喜欢的记录会使用 userId 和 postId 添加到我的 Likes 表中。

现在,当用户查看帖子时,我想确定他们之前是否喜欢该帖子。我知道要这样做,我需要在我调用发布信息时在我的 get 请求中确定这一点。

当我调用帖子信息时,我需要检查 Likes 表以获取当前用户的 userId 和当前帖子的 postId 的记录。如果存在,那么我需要返回一个名为 isLiked 的参数并将其设置为 true,如果它不存在则 isLiked=false。

这是我的帖子模型:

id: {
  type: Sequelize.INTEGER,
  primaryKey: true,
  autoIncrement: true,
},
title: {
  type: Sequelize.STRING,

},
userId: {
  type: Sequelize.INTEGER,
},
likesCount:{
  type:Sequelize.INTEGER,
  defaultValue:0,
  validate: {
            min: 0,
        }
},

这是我的点赞模型:

id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
 },
 PostId: {
type: Sequelize.INTEGER,
references: {
  model: "Post",
  key: "id",
},
 },
 userId: {
type: Sequelize.INTEGER,
references: {
  model: "User",
  key: "id",
},
 },

这是我的用户模型:

id: {
  type: Sequelize.INTEGER,
  primaryKey: true,
  autoIncrement: true,
},
name: {
  type: Sequelize.STRING,
 },

这是我的联想:

User.hasMany(Post, { foreignKey: "userId" });
Post.belongsTo(User, { foreignKey: "userId" });

Post.hasMany(Likes, { foreignKey: "PostId", targetKey: "id" });
Likes.belongsTo(Post, { foreignKey: "PostId", targetKey: "id" });

User.hasMany(Likes, { foreignKey: "userId", targetKey: "id" });
Likes.belongsTo(User, { foreignKey: "userId", targetKey: "id" });

更新

我一直在研究并发现,因为我正在使用 JWT 中间件来签署我的用户令牌,并且我目前正在检查当前用户是否在 likes 表中有任何记录,我尝试了以下但有人可以告诉我是否这种做法正确吗?

 router.get("/", async (req, res) => {
    const posts = await Post.findAll({
   order: [["createdAt", "DESC"]],
   include: [
  { model: Post_Image, attributes: ["id", "images"] },
  { model: Likes, attributes: ["id", "PostId", "userId"] },
  ],
  });

 if (!posts) return res.status(404).send();

 const baseUrl = config.get("assetsBaseUrl");

 const plainPosts = posts.map((x) => x.get({ plain: true }));
 const resultPosts = [];
  for (const post of plainPosts) {

 let isLiked = false;
 let like = await Likes.findOne({
where: {
[Op.and]: [{ PostId: post.id) }, { userId: 
req.user.id }],

  },
 });

if (like) isLiked = true;

const { Post_Images, ...postAttributes } = post;
const IMAGES = Post_Images.map((postImage) => ({
  url: `${baseUrl}${postImage.images}_full.jpg`,
  thumbnailUrl: `${baseUrl}${postImage.images}_thumb.jpg`,
}));
resultPosts.push({ ...postAttributes, images: IMAGES, isLiked 
});
}

res.send( resultPosts );

 });

【问题讨论】:

  • 显示整个路线以及如何发送请求以获取 isLiked
  • 嗨@Anatoly,我正在尝试在我的get all posts请求中创建一个查询,检查likes表中的userId记录和postId如果这个记录存在,那么我将返回一个名为is的参数喜欢并将其设置为 true,如果不存在 isLiked=false。我尝试在我的 for(const post of plainPosts){} 循环中实现这一点。我用一个例子更新了我的问题。谢谢
  • 我认为您需要简化它。有很多问题和困惑。直接说出你需要什么和你做了什么。删除不需要变得更好的信息。我会尝试为您编辑您的帖子。

标签: node.js sequelize.js


【解决方案1】:

您不需要指定所有字段,除非您想覆盖某些内容,否则 Sequelize 可以为您生成大部分列。

const User = sequelize.define(
  'user',
  {
    name: {
      type: Sequelize.STRING,
    },
  },
  { /* options */ }
);

const Post = sequelize.define(
  'post',
  {
    title: {
      type: Sequelize.STRING,
    },
  },
  { /* options */ }
);

// the join table so you can reference it, but doesn't need any columns including primary key (unless you want to a "super join")
const Likes = sequelize.define(
  'likes',
  {}, // no columns here
  { /* options */ }
);

创建模型之间的关联将自动创建大部分外键字段。在Likes 关系上使用through 关键字使其成为多对多。


// Users can have many Posts
User.hasMany(Post);

// Posts belong to one User
Post.belongsTo(User);

// Users can like more than one Post through the `likes` join table
User.hasMany(Post, { as: 'likes', through: 'likes' });

// Posts can be liked by more than one User through the `likes` join table
Post.hasMany(User, { as: 'likes', through: 'likes' });

您不需要存储喜欢的数量,因为您可以通过连接表对其进行汇总。

// Get the 'likes' count for a Post, instead of saving it on the post
const posts = await Post.findAll({
  attributes: {
    include: [
      [sequelize.fn('COUNT', sequelize.col('likes.userId')), 'likesCount'],
    ],
  },
  include: [
    {
      model: User,
      as: 'likes',
      though: 'likes',
      attributes: [],
      required: false,
    },
  ],
});

// `posts` will be an array of Post instances that have a likesCount property
posts.forEach((post) => {
  console.log(`The post ${post.title} has ${post.likesCount} likes.`);
});

对于单个(或多个)帖子,您可以通过帖子获得喜欢它的用户列表(或使用Like 模型及其关系)。


// Get the user 'likes' for a Post
const post = await Post.findByPk(postId, {
  include: [
    {
      model: User,
      as: 'likes',
      though: 'likes',
      required: false,
    },
  ],
});

post.likes.forEach((like) => {
  console.log(`The user ${like.name} has liked the post ${post.title}.`);
});

【讨论】:

  • 嗨@doublesharp,感谢您回复我。为什么喜欢和用户之间的关联是多对多的,我认为它是一对多,因为一个用户可以有很多喜欢,但一个喜欢只属于一个用户。另外,我正在尝试创建一个 isLiked 参数,它可以是真或假,我可以在我的前端使用。我已经有另一个正常工作的获取请求,可以让我得到每个用户的喜欢。我只是想在获取所有帖子时创建一个查询,以查看用户之前是否喜欢过这篇文章。再次感谢您
  • 我还编辑了问题并添加了我当前使用的关联。
【解决方案2】:

您无需再次请求Like,所有帖子的赞都在您手边:

for (const post of plainPosts) {
 // check if we have any like among posts' likes that is made by a certain user
 const isLiked = post.Likes.some(x => x.userId === req.user.id);
 const { Post_Images, ...postAttributes } = post;
 ...

【讨论】:

  • 感谢您回复我,对于每个帖子,我需要在数据库中检查是否有此 userId 和 postId 的记录。
  • 它只是有一个不必要的请求Likes.findOne。顺便说一句,您可以像这样简化where 选项中的条件:where: { PostId: post.id, userId: req.user.id } 因为您有 AND 条件并且条件中有不同的字段
  • 是的,你可以。您甚至可以使用count 而不是findOne,因为您不需要找到的记录本身。
  • 没有必要在请求的帖子中请求已经在其他喜欢中请求的喜欢。您只需要确定其中某个用户是否点赞即可。
  • some 只是检查给定数组的任何元素是否满足特定条件。见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-12
  • 2018-01-16
  • 1970-01-01
  • 2020-12-12
相关资源
最近更新 更多