MongooseJS populate using multiple target fields

2.9k Views Asked by At

I have the following two Schemas:

var MessageModel = mongoose.model("message",
    new Schema({
        sender:{type:ObjectId,ref:"user"},
        recipient:{type:ObjectId,ref:"user"},
        title: String
    })
);

var UserModel = mongoose.model("user", 
    new Schema({
        username: String,
        name: String,
        fname: String,
        messages:[{type:ObjectId,ref:"message"}]
    })
);

What I can't find anywhere is how does mongoose determine where to get the 'message' populating from - the 'sender' field or 'recipient' field...

Is it one? both? Can this be configured? i.e. can I create separate 'incomingMessage' and 'outgoingMessages' fields and how?

10x.

1

There are 1 best solutions below

2
On BEST ANSWER

I don´t know whether I understand this correctly, but it is in any way very clear what Mongoose is populating at any time.

If you run Message.find().populate('sender recipient').exec(..), you get every document with sender and recipient being their respective MongoDB documents.

If you run User.find().populate('messages').exec(..), you get an array of every message matching the ObjectId. By your design we cannot know whether the user is the sender or recipient. But if you know the user´s id in advance, we can filter for it:

User.find().populate({
    path: 'messages',
    match: { sender: userId }
}).exec(..)

This will return all messages where userId is the sender. The messages array however is in return not populated, meaning that you will have only the receivers id, but not its name, what in most use cases you probably want to have in those situation. So now you have to populate or select users by those ids again.

But remember this, if you find yourself populating over and over again, you have to rethink your design or MongoDB might not be the right solution after all.

Your design looks like you have a background with relational databases, storing no redundant information and sticking to database normalization rules. But MongoDB is not about relations. Even though it might sound weird to you, but think of storing the needed user name right within the message object.

You might be thinking that this way information will be outdated once the user changes its name, and you are correct. But how many times does a user really change his name compared to how many times he writes and receives messages. So rather update the messages model every once in while when a users changes his name, than populating over and over again.