Mongoose Private Chat Message Model

后端 未结 2 401
情书的邮戳
情书的邮戳 2021-02-03 15:24

I\'m trying to add private messaging between users into my data model. I\'ve been going back and forth between two possible ways of doing this.

1) Each user has an ar

相关标签:
2条回答
  • 2021-02-03 15:59

    A few suggestions.

    First - why store Participant1 and 2 as arrays? There is one specific sender, and one (or more) recipients (depending on if you want group messages).

    Consider the following Schema:

    var ChatSchema = new Schema({
        sender : {
            type : mongoose.Schema.Types.ObjectId,
            ref : 'User'
        },
        messages : [
            {
                message : String,
                meta : [
                    {
                        user : {
                            type : mongoose.Schema.Types.ObjectId,
                            ref : 'User'
                        },
                        delivered : Boolean,
                        read : Boolean
                    }
                ]
            }
        ],
        is_group_message : { type : Boolean, default : false },
        participants : [
            {
                user :  {
                    type : mongoose.Schema.Types.ObjectId,
                    ref : 'User'
                },
                delivered : Boolean,
                read : Boolean,
                last_seen : Date
            }
        ]
    });
    

    This schema allows one chat document to store all messages, all participants, and all statuses related to each message and each participant.

    the Boolean is_group_message is just a shorter way to filter which are direct / group messages, maybe for client side viewing or server-side processing. Direct messages are obviously easier to work with query-wise, but both are pretty simple.

    the meta array lists the delivered/read status, etc, for each participant of a single message. If we weren't handling group messages, this wouldn't need to be an array, but we are, so that's fine.

    the delivered and read properties on the main document (not the meta subdocument) are also just shorthand ways of telling if the last message was delivered/read or not. They're updated on each write to the document.

    This schema allows us to store everything about a chat in one document. Even group chats.

    0 讨论(0)
  • 2021-02-03 16:16

    Well, there is no correct answer to this question, But definitely, the approaches you have mentioned are not the best at all!

    Firstly, when you are thinking about designing a "chat" model, you need to take into account that there would be millions of messages between the users, so you need to care about performance when you want to fetch the chats.

    Storing the messages into an array is not a good idea at all, your model's size will be large by the time and you have to consider that MongoDB's document size limit is currently 16 MB per document.

    https://docs.mongodb.com/manual/reference/limits/

    Secondly, You have to consider pagination aspect because it will affect the performance when the chat is large, when you retrieve the chat between 2 users you won't request all the chats since the beginning of the time, you will just request the most recent ones, and then you can request the older ones if the user scroll the chat, this aspect is very important and can't be neglected due to its effect on performance.

    My approach will be to store each message in a separated document

    First of all, storing each message in a single document will boost your performance during fetching the chats, and the document size will be very small.

    This is a very simple example, you need to change the model according to your needs, it is just to represent the idea:

    const MessageSchema = mongoose.Schema({
        message:{
            text: { type:String, required:true }
            // you can add any other properties to the message here.
            // for example, the message can be an image ! so you need to tweak this a little
        }
        // if you want to make a group chat, you can have more than 2 users in this array
        users:[{
            user: { type:mongoose.Schema.Types.ObjectId, ref:'User', required:true }
        }]
        sender: { type:mongoose.Schema.Types.ObjectId, ref:'User', required:true },
        read: { type:Date }
    },
    {
        timestamps: true
    });
    

    you can fetch the chats by this query:

     Message.find(({ users: { "$in" : [#user1#,#user2#]} })
        .sort({ updatedAt: -1 })
        .limit(20)
    

    Easy and clean! as you see, pagination becomes very easy with this approach.

    0 讨论(0)
提交回复
热议问题