Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongoose dynamic references based on attribute

I want to have a dynamic reference based on another attribute in schema?

I have the following schemas, where location can be controlled by either a person or an organization (example a Office Building is controlled by a corporation, where as a Local Store is controlled by the owner).

// Has other fields - brief for simplicity.
var personSchema = new Schema({
    _id: {type: String, required: true},
    name: {type: String, required: true},
}); 
var PersonData = mongoose.model('PersonData', personSchema ); 


// Has other fields - brief for simplicity.
var organizationSchema = new Schema({
    _id: {type: String, required: true},
    name: {type: String, required: true},
    members: [{ type: String, ref: 'PersonData'}]
}); 
var OrganizationData = mongoose.model('OrganizationData', organizationSchema ); 

var locationSchema = new Schema({
    _id: {type: String, required: true},
    name: {type: String, required: true},
    controlledBy:{ 
            type: {String, enum: [ 'Organization', 'Individual']},
            controller: { type: String, ref: 'PersonData' or 'OrganizationData'}
    }
});

I guess one option would be to put two fields in "controlledBy" but not sure if that is the best way to do it?

controlledBy:{ 
    type: {String, enum: [ 'Organization', 'Individual']},
    individual: { type: String, ref: 'PersonData' },
    organization: { type: String, ref: 'OrganizationData'}
}

With the above I think I could maybe drop the type then?

like image 703
Syrkres Avatar asked Mar 23 '26 01:03

Syrkres


1 Answers

I had a similar problem and I used the same solution you used. But then, I got introduced to Dynamic Referencing with refPath. The difference between ref and refPath is that with refPath, you can configure what model Mongoose uses for each document instead of the hardcoded String with ref. A solution I would suggest for you would be:

controllerType:{ 
  type: String,
  enum: [ 'Organization', 'Individual']
},
controllerId: {
  type: Schema.Types.ObjectId,
  refPath: 'controllerType'
}

like image 181
Ikdemm Avatar answered Mar 24 '26 16:03

Ikdemm