如何获取每个用户的对话并包含消息?

How to get the conversations for each user and include the messages?

我正在尝试让每个用户的对话显示在我前端的收件箱屏幕上。我能够将 post 消息发送到数据库,但是当我尝试获取它们时,我不断收到

[SequelizeEagerLoadingError]: Message is not associated to Conversation!

谁能看看我的代码。

这是我的获取请求:

router.get('/', auth, (req, res) => {
  Conversation.findAll({
    where: {
      [Op.or]: [
        {
          user1: { [Op.eq]: req.user.id },
          user2: { [Op.eq]: req.user.id },
        },
      ],
    },
    include: [{ model: Message }],
  })
    .then(() => res.send())
    .catch((err) => console.log(err));
});

这是我的对话模型

const Conversation = db.define('Conversation', {
});

module.exports = Conversations;

Conversation.associate = (models) => {
  Conversation.hasMany(models.Message, {
    foreignKey: 'conversationId',
  });

  Conversation.belongsTo(models.Post, {
    foreignKey: 'PostId',
  });
};

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

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

这是我的消息模型:

const Message = db.define('Message', {
  id: {
    primaryKey: true,
    type: Sequelize.INTEGER,
  },
  senderId: {
    type: Sequelize.STRING,
  },
  receiverId: {
    type: Sequelize.STRING,
  },
  message: {
    type: Sequelize.STRING,
  },
  conversationId: {
    type: Sequelize.INTEGER,
  },
});

module.exports = Message;

User.hasMany(Message, {
  foreignKey: 'senderId',
  as: 'SentMessage',
});

User.hasMany(Message, {
  foreignKey: 'receiverId',
  as: 'ReceivedMessage',
});

Message.associate = (models) => {
  Message.belongsTo(models.User, {
    foreignKey: 'senderId',
    as: 'Sender',
  });

  Message.belongsTo(models.User, {
    foreignKey: 'receiverId',
    as: 'Receiver',
  });

  Message.belongsTo(models.Conversation, {
    foreignKey: 'conversationId',
  });
};

Post.hasMany(Conversation, { foreignKey: 'PostId' });

更新

移除后

Conversation.hasMany(models.Message,{foreginKey:"conversationId"}) 

从我的对话模型中的关联方法并将其添加到我的消息模型中,我不再收到关联错误,但现在当我尝试测试获取请求时,当我的数据库充满条目时,我不断收到空响应。

这是我更新的获取请求:

router.get('/',auth,async(req,res)=>{
const conversation = await Conversations.findAll({
include:[{
 model:Message,
required: false,
}],
where:{
[Op.or]:[{
user1:{[Op.eq]:req.user.id},
user2:{[Op.eq]:req.user.id},
}]
},
});

if(!conversation) return res.send().catch(err=>console.log(err)) 

res.status(200).send()

})

这是我在终端中的回复:

 Executing (default): SELECT "Conversation"."id", 
 "Conversation"."createdAt", "Conversation"."updatedAt", 
 "Conversation"."user1", "Conversation"."user2", 
 "Conversation"."PostId", "Messages"."id" AS "Messages.id", 
 "Messages"."senderId" AS "Messages.senderId", 
 "Messages"."receiverId" AS 
 "Messages.receiverId", 
 "Messages"."message" AS "Messages.message", 
 "Messages"."conversationId" AS "Messages.conversationId", 
 "Messages"."createdAt" AS "Messages.createdAt", 
 "Messages"."updatedAt" AS "Messages.updatedAt" FROM "Conversations" 
 AS "Conversation" LEFT OUTER 
 JOIN "Messages" AS "Messages" ON "Conversation"."id" = 
 "Messages"."conversationId" WHERE (("Conversation"."user1" = 43 AND 
 "Conversation"."user2" = 43));

const { 用户 } = require("./containers/api/config/database")

您可以进行一些改进 - 示例代码中的问题是 MessagesUser 之间存在多个关系,因此您需要指定 as 关键字Sequelize 知道使用哪个。如果没有关联中的 as,你就没有任何关系,据 Sequelize 可以看出没有关系。

我会让 Sequelize 自动为主键和外键生成大部分列,以保持简单。使用单数 table 名称并让 Sequelize 在可以返回多个结果时将它们复数化也是一种很好的做法,例如 Post.getConversations()Message.getConversation()。如果可以的话,使用 async/await 而不是 thenables 也更具可读性。

您应该能够将 where 移动到 Message 包含并添加 required: true 使其成为 RIGHT JOIN.

型号

const User = db.define('user', {
  // fields go here
});

const Post = db.define('post', {
  // fields go here
});

const Conversation = db.define('conversation', {
  // don't define columns, they will be generated
});

const Message = db.define('message', {
  message: {
    type: Sequelize.STRING,
  },
  // more fields
});

协会

// Message -- Conversation, creates message.conversationId NOT NULL
Message.belongsTo(Conversation, { allowNull: false });
// Conversation -< Messages, uses message.conversationId
Conversation.hasMany(Message);

// Conversation -- User, creates conversation.creatorId NOT NULL
Conversation.belongsTo(User, { as: 'Creator', foreignKey: 'creatorId', allowNull: false });
// User -< Conversations, uses conversation.creatorId
User.hasMany(Conversation, { as: 'CreatedConversations', foreignKey: 'creatorId' });

// Message -- User, creates message.senderId NOT NULL
Message.belongsTo(User, { as: 'Sender', foreignKey: 'senderId', allowNull: false });
// User -< Message (Sent), join user.id = message.senderId
User.hasMany(Message, { as: 'Sent', foreignKey: 'senderId' });

// Message -- User, creates message.receiverId NOT NULL
Message.belongsTo(User, { as: 'Receiver', foreignKey: 'receiverId', allowNull: false });
// User -< Message (Received), join user.id = message.receiverId
User.hasMany(Message, { as: 'Received', foreignKey: 'receiverId' });

// Conversation -- Post, creates conversation.postId NOT NULL
Conversation.belongsTo(Post, { allowNull: false });
// Post -< Conversations, uses conversation.postId
Post.hasMany(Conversation);

查询 获取用户在消息中作为发送者或接收者的所有对话。

router.get('/', auth, async (req, res) => {
  try {
    const conversations = await Conversation.findAll({
      include: [{
        model: Message,
        where: {
          [Op.or]: [
            { senderId: req.user.id }, 
            { receiverId: req.user.id },
          ],
        },
        required: true, // RIGHT  JOIN
      }],
    });
    return res.json(conversations);
  } catch (err) {
    console.log(err);
    return res.status(500).send(err);
  }
});

查询 获取用户创建的所有对话。这取代了对话中的 user1user2,但您可能仍希望它用于其他用途。

router.get('/created_conversations', auth, async (req, res) => {
 try {
   const conversations = await Conversation.findAll({
     include: [{
       model: Message,
       required: false, // LEFT  JOIN
     }],
     where: {
       creatorId: req.user.id
     },
   });
   return res.json(conversations);
 } catch (err) {
   console.log(err);
   return res.status(500).send(err);
 }
});
router.get('/user', auth, async (req, res) => {
  try {
    const user = await User.findByPk(req.user.id, {
      include: [{
        model: Conversation,
        as: 'CreatedConversations',
        required: false, // LEFT  JOIN
        include: [{
          model: Message,
          required: false, // LEFT  JOIN
        }],
      }],
    });

    // const conversations = user.getConversations();
    // const [conversation] = conversations; // get the first result
    // const messages = conversation.getMessages();

    return res.json(user);
  } catch (err) {
    console.log(err);
    return res.status(500).send(err);
  }
});

在 Anatoly 和 doublesharp 的帮助下尝试解决这个问题很多天后,我终于弄明白了。

我的问题是我的对话模型中的关联方法由于某种我仍然不知道的原因没有被执行,所以我将它从我的对话模型中的关联方法中删除并将它添加到我的消息模型中并且它有效.

这是我的代码:

消息模型:

const Message = db.define("Message", {
senderId: {
type: Sequelize.STRING,
},
receiverId: {
type: Sequelize.STRING,
},
message: {
type: Sequelize.STRING,
},
conversationId:{
type: Sequelize.INTEGER,
}
});

module.exports = Message;

User.hasMany(Message, {
as:"SentMessage",
foreignKey: 'senderId',
});

User.hasMany(Message, {
as:"ReceivedMessage",
foreignKey: 'receiverId',
});

Message.associate = (models) => {

Message.belongsTo(models.User, {
as:"Sender",
foreignKey: "senderId",
allowNull: false 
});
Message.belongsTo(models.User, {
as:"Receiver",
foreignKey: "receiverId",
allowNull: false 
});
Message.belongsTo(models.Conversations, { allowNull: false },{
foreignKey: "conversationId",
}
};

Conversation.hasMany(Message,{
foreignKey: "conversationId",
}
);

这是我的对话模型:

const Conversation = db.define("Conversation", {});

module.exports = Conversation;

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

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

 Conversation.belongsTo(User, { as: 'Creator', foreignKey: 'user1', allowNull: 
 false })
 Conversation.belongsTo(User, { as: 'Recipient', foreignKey: 'user2', 
 allowNull: false })

这是我的 Post 模型协会:

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

Conversation.belongsTo(Post,{
foreignKey: "PostId",
allowNull: false 
})

这是我的 GET 请求:

router.get('/', auth, async (req, res) => {
try {
const conversations = await Conversation.findAll({
  include: [{
    model: Message,
    where: {
      [Op.or]: [
        { senderId: req.user.id }, 
        { receiverId: req.user.id },
      ],
    },
    required: true, // RIGHT  JOIN
  }],
});
return res.json(conversations);
} catch (err) {
console.log(err);
return res.status(500).send(err);
}
});

这是我的 Post 回复:

[
{
    "id": 1,
    "user1": 43,
    "user2": 45,
    "PostId": 523,
    "Messages": [
        {
            "id": 1,
            "senderId": 43,
            "receiverId": 45,
            "message": "My first message & Conversation",
            "conversationId": 1,
        }
    ]
  },
  {
    "id": 4,
    "user1": 43,
    "user2": 45,
    "PostId": 522,
    "Messages": [
        {
            "id": 7,
            "senderId": 43,
            "receiverId": 45,
            "message": "One more time",
            "conversationId": 4,
        },
    ]
    },
  {
    "id": 5,
    "user1": 45,
    "user2": 43,
    "PostId": 518,
    "Messages": [
        {
            "id": 11,
            "senderId": 45,
            "receiverId": 43,
            "message": "Hello 43",
            "conversationId": 5,
        }
    ]
}
]