Mongoose schema mixed type field errantly saving ObjectId field as a String

857 views Asked by At

I am working on chat application and each Event in a conversation has a field named sender - looks like this:

var eventSchema = Schema({
    sender: {
        type: {}, //username && user_id fields
        required: true
    }
}

Every time that an Event is created, I pass in object that looks like this for the sender field:

{
    username: String,
    user_id: ObjectId("")
}

I am positive that the user_id field in Event.sender is of type ObjectId every time.

However, in the database the saved events sometimes have Event.sender.user_id of type String && other times Event.sender.user_id saved as type ObjectId().

{
    username: String,
    user_id: ObjectId("")    // sometimes it saves like this
}

{
    username: String,
    user_id: String    // other times it saves like this
}

The variation happens fairly frequently, and there are events sent by the same user, passing through the same controller function within a 10 minutes time frame exhibiting this variation.

Is there a certain behavior in Mongoose that I am not accounting for which affects how ObjectIds are saving within a Schema's mixed type field?

This behavior happens on saves, not updates. There are no updates being made to the Event.sender field within the system.

1

There are 1 answers

0
Jorge Olivero On

So the answer was fairly obscure, in that it was hidden from us in our development environments . The issue occurs only when the Node process is clustered, which we only really see in production. Turns out we were passing Mongoose a stringified version of user_id, so the problem was in our lack of understanding of how the Redis Store mechanism works.

In production, we use redis store to manage sessions across Node processes for socket.io. So, in the middle of a handshake, an http request might make it to different process than the one that you initially began the handshake with. Redis Store then stringifies the handshake object and sends it to all other running processes.

Because of that stringify, the ObjectId wrapper on the user_id that we use in many places within our application gets lost and we end up saving strings within the sender object for many of our events.

Hope this helps someone down the line.