Sequelize how to structure the chat part of the app?

六月ゝ 毕业季﹏ 提交于 2020-12-07 16:41:02

问题


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?

Update

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'
});

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

Here is my post request:

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);

});

回答1:


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'
});

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.

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);

should be in Message model associate method:

Message.belongsTo(models.Conversations);

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

UPDATE

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",
});

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).



来源:https://stackoverflow.com/questions/65168123/sequelize-how-to-structure-the-chat-part-of-the-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!