title: How to create MongoDB schema design while dealing with single User account and multiple user (Organization account with roles)
body: <p>I am working on a Nodejs Express API project using mongoDB with mongoose  and i would like to  get some advice on best practices and going about creating an efficient schema design from community</p>
  
  <p>The app deals with two type of user accounts </p>
  
  <p>Account type : </p>
  
  <ul>
  <li>Single (default)</li>
  <li>Organization (can switch to from settings)</li>
  </ul>
  
  <p><strong>Note</strong>:
  <strong>In organisation account there will be a admin (owner) and other invited user and  each user is assigned permission level / access level .One user will always be associated with only one account, ie he cannot be invited again to another account  or start a new account if he is already part of a existing account. Also billing and shipping address is specific to account rather than user in the case of an organization account (address of user switching to organization account will be the address of Organization account )</strong> </p>
  
  <p>I have completed the  authentication part  with the help of  <strong>passport.js</strong>  <strong>JWT</strong> and <strong>local strategy</strong></p>
  
  <p>i tried to develop one similar to RDBMS approach ( i used to be RDBMS guy ) and failed </p>
  
  <p><a href="https://i.stack.imgur.com/jK5Uv.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/jK5Uv.png" alt="enter image description here"></a></p>
  
  <p><strong>Models and schemas</strong></p>
  
  <pre><code>const userSchema = new Schema({
      first_name: String,
      last_name: String,
      email: String,
      phone: String,
      avatar: String,
      password: String,
      active: Boolean
  });
  
  const User = mongoose.model('user', userSchema);
  
  const accountSchema =  mongoose.Schema({
      account_type: { type: String, enum: ['single', 'organization'], default: 'single' },
      organization: { type: Schema.Types.ObjectId, ref: 'organization', required: false },
      billing_address: String,
      shipping_address: String,
  
  });
  
  const Account = mongoose.model('account', accountSchema);
  
  const accountUserRoleSchema =  mongoose.Schema({
      user :  { type: Schema.Types.ObjectId, ref: 'user', },
      role: { type: String, enum: ['admin', 'user'], default: 'user' },
      account: { type: Schema.Types.ObjectId, ref: 'account', required: true  }
  });
  
  const AccountUserRole = mongoose.model('accountUserRole', accountUserRoleSchema);
  
  
  const permissionSchema =  mongoose.Schema({
      user :  { type: Schema.Types.ObjectId, ref: 'user', required: true },
      type: {  type: Schema.Types.ObjectId, ref: 'permissionType', required: true  },
      read: { type: Boolean, default: false, required: true  },
      write: { type: Boolean, default: false, required: true },
      delete: { type: Boolean, default: false, required: true },
      accountUser : {  type: Schema.Types.ObjectId, ref: 'account',required: true }
  
  });
  
  const Permission = mongoose.model('permission', permissionSchema);
  
  
  const permissionTypeSchema =  mongoose.Schema({
      name :  { type: String, required: true   }
  
  });
  
  const PermissionType = mongoose.model('permissionType', permissionTypeSchema); 
  
  
  const organizationSchema =  mongoose.Schema({
      account :  { type: Schema.Types.ObjectId, ref: 'account', },
      name: {  type: String, required: true },
      logo: { type: String, required: true  }
  });
  
  
  const Organization = mongoose.model('organization', organizationSchema);
  </code></pre>
  
  <p>Now i am developing Authorisation part where the user need to be restricted access to the resource by checking the permission he or she is assigned with .</p>
  
  <p>The solution i found was to develop a Authorisation middleware which run after the authentication middleware which check for the access permissions assigned   </p>
  
  <p>But the problem appeared while i tried to access account data  based on the user currently logged in , as i will have to search document based on the objectId reference .  And i could  understand that this could happen if i continue with my current design .This works fine but searching document using objectId reference seems not be a good idea </p>
  
  <p><strong>Authorization middleware</strong></p>
  
  <pre><code>module.exports = {
  
      checkAccess :  (permission_type,action) =&gt; {
  
          return  async (req, res, next) =&gt; {
  
              // check if the user object is in the request after verifying jwt
              if(req.user){
  
                  // find the accountUserRole with the user data from the req after passort jwt auth
                  const accountUser = await AccountUserRole.findOne({ user :new ObjectId( req.user._id) }).populate('account');
                  if(accountUser)
                  {
                      // find  the account  and check the type 
  
                      if(accountUser.account)
                      {   
                          if(accountUser.account.type === 'single')
                          {   
                              // if account  is single grant access
                              return next();
                          }
                          else if(accountUser.account.type === 'organization'){
  
  
                               // find the user permission 
  
                               // check permission with permission type and see if action is true 
  
                               // if true move to next middileware else throw  access denied error  
  
  
                          }
                      }
  
                  }
  
              }
          }
  
  
      }
  
  
  }
  </code></pre>
  
  <p>I decided to scrap my current schema as i understand that forcing RDBMS approach on NoSQL is a bad idea.</p>
  
  <p><strong>Unlike relational databases, with MongoDB the best schema design depends a lot on how you're going to be accessing the data. What will you be using the Account data for, and how will you be accessing it</strong></p>
  
  <p><strong>My new redesigned schema and models</strong></p>
  
  <pre><code>const userSchema = new Schema({
      first_name: String,
      last_name: String,
      email: String,
      phone: String,
      avatar: String,
      password: String,
      active: Boolean
      account :  { type: Schema.Types.ObjectId, ref: 'account', },
      role: { type: String, enum: ['admin', 'user'], default: 'user' },
      permssion: [
          {
              type: {  type: Schema.Types.ObjectId, ref: 'permissionType', required: true  },
              read: { type: Boolean, default: false, required: true  },
              write: { type: Boolean, default: false, required: true },
              delete: { type: Boolean, default: false, required: true },
          }
      ]
  
  });
  
  const User = mongoose.model('user', userSchema);
  
  const accountSchema =  mongoose.Schema({
      account_type: { type: String, enum: ['single', 'organization'], default: 'single' },
      organization: {  
              name: {  type: String, required: true },
              logo: { type: String, required: true  }
           },
      billing_address: String,
      shipping_address: String,
  
  });
  
  
  const Account = mongoose.model('account', accountSchema);
  
  
  const permissionTypeSchema =  mongoose.Schema({
      name :  { type: String, required: true   }
  
  });
  
  const PermissionType = mongoose.model('permissionType', permissionTypeSchema);
  </code></pre>
  
  <p>Still i am not sure if this is the right way to do it ,  please help me with you suggestions.   </p>