To implement a chat application using MongoDB’s data model patterns, follow these key steps:
1. Schema Design
Users Collection (Referencing Pattern)
Stores user details and chat references.
{
"_id": ObjectId("user1_id"),
"username": "Ram",
"contacts": [{ "user_id": ObjectId("user2_id"), "chat_id": ObjectId("chat1_id") }]
}
Chats Collection (Embedding for metadata, Referencing for messages)
Stores chat metadata and participants.
{
"_id": ObjectId("chat1_id"),
"type": "private",
"participants": [ObjectId("user1_id"), ObjectId("user2_id")],
"last_message": { "text": "Hello!", "sender": ObjectId("user1_id"), "timestamp": ISODate("2025-02-22T10:30:00Z") }
}
Messages Collection (Bucket Pattern)
Groups messages by date for efficient retrieval.
{
"_id": ObjectId("bucket1"),
"chat_id": ObjectId("chat1_id"),
"date": "2025-02-22",
"messages": [
{ "sender": ObjectId("user1_id"), "text": "Hello!", "timestamp": ISODate("2025-02-22T10:30:00Z") },
{ "sender": ObjectId("user2_id"), "text": "Hi!", "timestamp": ISODate("2025-02-22T10:31:00Z") }
]
}
2. Indexing for Performance
db.messages.createIndex({ "chat_id": 1, "messages.timestamp": -1 });
3. API Implementation (Node.js + Express + MongoDB)
Send Message
app.post('/send', async (req, res) => {
const { chatId, senderId, text } = req.body;
await Message.findOneAndUpdate(
{ chat_id: chatId, date: new Date().toISOString().split('T')[0] },
{ $push: { messages: { sender: senderId, text, timestamp: new Date() } } },
{ upsert: true }
);
res.send("Message sent!");
});
Get Messages
app.get('/messages/:chatId', async (req, res) => {
const messages = await Message.find({ chat_id: req.params.chatId }).sort({ "messages.timestamp": -1 }).limit(10);
res.json(messages);
});