Sequelize 如何构建应用程序的聊天部分? [英] Sequelize how to structure the chat part of the app?

查看:59
本文介绍了Sequelize 如何构建应用程序的聊天部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前有一个应用程序,用户可以在其中登录并发帖.每个帖子旁边都有一个按钮,如果按下,当前用户可以向创建帖子的用户发送消息.

I currently have an app where users can log in and make posts. Next to each post, there is button that if pressed, the current user can send a message to the user who created the post.

我有一个帖子模型和一个用户模型.每个用户可以发布任意数量的帖子,但每个帖子只属于一个用户.

I have a posts model and a user model. Each user can post as many posts as they want, but each post only belongs to one user.

const User = db.define(
"User",
{
id: {
  type: Sequelize.INTEGER,
  primaryKey: true,
  autoIncrement: true,
},
name: {
  type: Sequelize.STRING,
  },
email: {
  type: Sequelize.STRING,
},
password: {
  type: Sequelize.STRING,
},
},
);

const Post = db.define(
"Post",
{
id: {
  type: Sequelize.INTEGER,
  primaryKey: true,
  autoIncrement: true,
},
title: {
  type: Sequelize.STRING,
},
subTitle: {
  type: Sequelize.STRING,
},
userId: {
  type: Sequelize.INTEGER,
},
},
);

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

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

我现在想要实现的是消息传递功能.

What i am trying to implement now is the messaging functionality.

这是我目前的消息模型:

Here is my messages Model so far:

  const Messages = db.define("Messages", {
  id: {
  allowNull: false,
  autoIncrement: true,
  primaryKey: true,
  type: Sequelize.INTEGER,
  },
 senderId: {
 type: Sequelize.STRING,
 },
 receiverId: {
 type: Sequelize.STRING,
 },
 message: {
 type: Sequelize.STRING,
 },
});

User.hasMany(Messages, {
foreignKey: 'senderId'
});

User.hasMany(Messages, {
foreignKey: 'receiverId'
});

Messages.associate = (models) => {
Messages.belongsTo(models.Post, {
foreignKey: "PostId",
});
Messages.belongsTo(models.User, {
foreignKey: "senderId",
});
Messages.belongsTo(models.User, {
foreignKey: "receiverId",
});
};

User.hasMany(Conversations, {
foreignKey: 'conversationId'
});

这是我目前的对话模型:

And here is my conversation model so far:

const Conversations = db.define("Conversations", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
}
});

module.exports = Conversations;

Conversations.associate = (models) => {
Conversations.hasMany(models.Message); 
models.Message.belongsTo(Conversations); 
};

此外,消息可以从一个用户发送到另一个用户,而不是一组用户.

Also, the message can be sent from 1 user to another not to a group of users.

我的关联和表结构是否正确?

Are my associations and table structures correct?

更新

User.hasMany(Messages, {
foreignKey: 'senderId'
});

User.hasMany(Messages, {
foreignKey: 'receiverId'
});

Messages.associate = (models) => {
Messages.belongsTo(models.User, {
foreignKey: "senderId",
});
Messages.belongsTo(models.User, {
foreignKey: "receiverId",
});
Messages.belongsTo(models.Conversations,{
foreignKey: "conversationId",
});
};

Conversations.associate = (models) => {
Conversations.hasMany(models.Messages,{
  foreignKey: "conversationId",
}); 
Conversations.belongsTo(models.Post,{
  foreignKey: "PostId",
})
};

Post.hasMany(Conversations, { foreignKey: "PostId" });

User.hasMany(Conversations, {
foreignKey: 'user1'
});

User.hasMany(Conversations, {
foreignKey: 'user2'
});

当我尝试发送消息时使用此实现,消息表中的conversationId 为空.

Using this implementation when i try sending a message, the conversationId in the messages table is null.

这是我的帖子请求:

router.post("/", 
auth, 
async (req, res) => {

const post = await Post.findOne({where:{id:req.body.postId}})
if (!post) return res.status(400).send({ error: "Invalid postId." });

const targetUser = await User.findOne({where:{post.userId}})
if (!targetUser) return res.status(400).send({ error: "Invalid 
userId." });

await Conversations.findOne({
where:{
  user1:{[Op.or]:[req.user.id,post.userId]},
  user2:{[Op.or]:[req.user.id,post.userId]},
  PostId:req.body.postId,
}
}).then(conversation=>{
if(conversation){
  return conversation
}else{
  return Conversations.create({
    user1: req.user.id,
    user2: post.userId,
    PostId:req.body.postId,
  })
}
}
)
  Messages.create({
  senderId: req.user.id,
  receiverId: post.userId,
  message: req.body.message,
  conversationId:conversation.id //MY PROBLEM IS HERE
})
.then(
  res.status(201).send({
    msg: "upload successful",
  }));

const { expoPushToken } = targetUser;

if (Expo.isExpoPushToken(expoPushToken))
await sendPushNotification(expoPushToken, message);

});

推荐答案

所有模型看起来都不错.问题在于关联.

All models look good. The issues are with associations.

如果您在相同的两个模型之间定义了多个关联,则应指定不同的别名,以便在查询中将它们区分开来.

If you define more then one association between the same two models you should indicate different aliases to distinguish them from each other in queries.

User.hasMany(Messages, {
foreignKey: 'senderId',
as: 'OutgoingMessages'
});

User.hasMany(Messages, {
foreignKey: 'receiverId',
as: 'IncomingMessages'
});

Messages.belongsTo(models.User, {
foreignKey: "senderId",
as: 'Sender'
});
Messages.belongsTo(models.User, {
foreignKey: "receiverId",
as: 'Receiver'
});

此外,最好在模型定义之后直接或在像 associate 这样的静态方法中以相同的方式定义关联.后一种方法更可取,因为它允许使用 associate 方法中的 models 参数在其自己的模块中定义每个模型而无需任何交叉引用来访问应该关联的其他模型使用给定的模型.

Also it's better to define associations in the same manner either directly after model definition or in a static method like associate. The latter approach is preferable because it allows to define each model in its own module without any cross-references using the models parameter in associate method to access other models that should be associated with a given model.

最后一点:尝试在自己的associate 方法中定义关联,其中关联定义左侧的模型.这意味着

Last note: try to define associations where a model on the left side of an association definition in its own associate method. It means that

models.Message.belongsTo(Conversations);

应该在Message模型associate方法中:

Message.belongsTo(models.Conversations);

这样您就始终知道在哪里可以找到定义从某个模型到其他模型的链接的所有关联.

That way you always know where to find all associations that define links from a certain model to other models.

更新

您应该将找到的或创建的对话存储到变量中,以便在创建消息时使用它:

You should store a found or a created conversation to a variable in order to use it while creating a message:

let conversation = await Conversations.findOne({
  where:{
    user1:{[Op.or]:[req.user.id,post.userId]},
    user2:{[Op.or]:[req.user.id,post.userId]},
    PostId:req.body.postId,
  }
})

if (!conversation){
  conversation = await Conversations.create({
    user1: req.user.id,
    user2: post.userId,
    PostId:req.body.postId,
  })
}
const newMessage = await Messages.create({
  senderId: req.user.id,
  receiverId: post.userId,
  message: req.body.message,
  conversationId:conversation.id
})
res.status(201).send({
  msg: "upload successful",
});

不要试图混淆then/catchawait.如果您使用 await,您将已经有结果或异常(您可以使用 try/catch 处理).

Don't try to mix up then/catch and await. If you use await you will already have a result or an exception (which you can handle using try/catch).

这篇关于Sequelize 如何构建应用程序的聊天部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆