В настоящее время у меня есть приложение, в котором пользователи могут входить в систему и публиковать сообщения. Рядом с каждым сообщением есть кнопка, при нажатии которой текущий пользователь может отправить сообщение пользователю, создавшему сообщение.

У меня есть модель сообщений и модель пользователя. Каждый пользователь может публиковать столько сообщений, сколько хочет, но каждое сообщение принадлежит только одному пользователю.

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

Сейчас я пытаюсь реализовать функцию обмена сообщениями.

Вот моя модель сообщений на данный момент:

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

И вот моя модель разговора на данный момент:

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

Также сообщение может быть отправлено от одного пользователя другому, а не группе пользователей.

Правильны ли мои ассоциации и структуры таблиц?

Обновить

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

Используя эту реализацию, когда я пытаюсь отправить сообщение, идентификатор беседы в таблице сообщений равен нулю.

Вот мой почтовый запрос:

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

});
0
kd12345 6 Дек 2020 в 15:37

1 ответ

Лучший ответ

Все модели хорошо выглядят. Проблемы связаны с ассоциациями.

Если вы определяете более одной связи между одними и теми же двумя моделями, вы должны указать разные псевдонимы, чтобы отличать их друг от друга в запросах.

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. Последний подход предпочтительнее, поскольку он позволяет определять каждую модель в ее собственном модуле без каких-либо перекрестных ссылок с использованием параметра models в методе associate для доступа к другим моделям, которые должны быть связаны с данной моделью.

Последнее замечание: попробуйте определить ассоциации, где модель находится слева от определения ассоциации, в собственном методе associate. Это означает, что

models.Message.belongsTo(Conversations);

Должен быть в методе Message модели associate:

Message.belongsTo(models.Conversations);

Таким образом, вы всегда будете знать, где найти все ассоциации, которые определяют ссылки от определенной модели к другим моделям.

ОБНОВЛЕНИЕ

Вы должны сохранить найденный или созданный диалог в переменной, чтобы использовать его при создании сообщения:

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/catch и await. Если вы используете await, у вас уже будет результат или исключение (которое вы можете обработать с помощью try/catch).

1
Anatoly 7 Дек 2020 в 08:19