Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose schema field names and types with subdocs

I'm building an object of field names and their types from my schema:

var ret = {};
ThisCollection.schema.eachPath(function(path) {
  ret[path] = ThisCollection.schema.path(path).instance;
});

Which is great unless there's a nested array in the schema. I can't seem to figure out how to access the subdocument and its fields' types. I've tried:

ThisCollection.schema.path("dot.notation").instance

within a recursive function building out the dot notation name of a deeper path. This does not appear to work.

Example schema:

 var Person = new Schema({
    person_code: String, 
    person_name: String, 
    location_details:[{
        location_name: String,
        location_code: String
    }]
});

To be clear, I'm looking for my return object to match my schema in structure as well, so that nested schemas are nested objects in my return object, something like:

{
    person_code: String,
    person_name: String,
    location_details:{
        location_name: String,
        location_code: String
    }
}
like image 895
Randy Hall Avatar asked Oct 24 '25 05:10

Randy Hall


2 Answers

The simplest solution may be to simply save off the schema definition object you're using to create your schema:

var personSchemaDef = {
    person_code: String,
    person_name: String,
    location_details: [{
        location_name: String,
        location_code: String
    }]
};
var personSchema = new Schema(personSchemaDef);
var Person = mongoose.model('person', personSchema, 'people');

But you can also get the hierarchical details of the schema from the tree property of the schema:

console.log(Person.schema.tree)

Output:

{ person_code: [Function: String],
  person_name: [Function: String],
  location_details:
   [ { location_code: [Function: String],
       location_name: [Function: String] } ],
  _id:
   { type: { [Function: ObjectId] schemaName: 'ObjectId' },
     auto: true },
  id:
   VirtualType {
     path: 'id',
     getters: [ [Function: idGetter] ],
     setters: [],
     options: {} },
  __v: [Function: Number] }
like image 165
JohnnyHK Avatar answered Oct 26 '25 19:10

JohnnyHK


The key here is to create an object from the paths, in particular the paths with the dot notation string. You can use the following method that sets an object given the property and value;

var ret = {};
var setObject = function(name, schema, context) {
    var parts = name.split("."), 
        p = parts.pop(),
        value = schema.path(p).instance;
    for(var i=0, j; context && (j=parts[i]); i++){
        context = (j in context ? context[j] : context[j]={});
    }        
    return context && p ? (context[p]=value) : undefined; // Object
}

ThisCollection.schema.eachPath(function(path) {         
    setObject(path, ThisCollection.schema, ret);        
});
like image 39
chridam Avatar answered Oct 26 '25 18:10

chridam