Search code examples
node.jsmongodbmongooserolerefs

Mongoose schema for arrays of refs with role


I'm very new to the NoSQL way of doing things so please excuse me if I'm just thinking about this completely wrong (I feel like I am).

My application has Users and Organizations, and the Users must have and belong to those Organizations with a role of member or owner.

Currently in my schema for my Users I have:

orgs: [{ type: Schema.Types.ObjectId, ref: 'Org' }]

and in my schema for my Organizations I have:

members: [{ type: Schema.Types.ObjectId, ref: 'User' }]

but I would also like to attach a role of member or owner to this.

Is this something I should put in the actual reference somehow like:

members: [{ type: Schema.Types.ObjectId, ref: 'User', role: String }]

or should the role be elsewhere in the schema? What is the proper way to handle this or is there a different way to schematize this that is more appropriate?

And once I have the schema set up for this properly, it would be helpful to have an example of how to create a few users/orgs with this roled ref.


Solution

  • You can do this with a small change to what you have there. I store messages in an app the same way (text and sender).

    Here's what you could do:

    members: [{
        role: { 
          type: String
        },
        user: { 
          type: mongoose.Schema.Types.ObjectId, 
          ref: 'User'
        }
      }],
    

    Then when you want to add a member or members to an organization (assume you have already created an organization and a user separately):

    function addNewMember(org_id, user_id, role) {   
        var member = {role: role, user: user_id};
        Organization.findByIdAndUpdate(org_id, {"$push": {"members":member}}, function(err,org) {
                   ...
                 });)  
    // you can use the $each clause to add a whole array of members at the same time too
    // like so:
    // {"$push": {"members": 
    //              {
    //              "$each": [memberarray]
    //              }}}
    
    }
    

    And when you want to find an organization including it's members, you could do:

        Organization.findById(org_id) 
            .populate('members.user')
            .exec(callbackfunction);
    

    Think carefully if you do absolutely need to duplicate the Organization -> member relationship for each member too as Member -> organizations. If this is indeed important, after successfully adding the user to the organization, in the callback you can do a second query to update the user's orgs field just like above.