Reputation: 8167
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
}
}
Upvotes: 4
Views: 6191
Reputation: 56
If you are looking to get the field names in a schema then this is a simple way to do it:
const schema = [dbname].schema;
const fieldNames = Object.keys(schema.obj);
This will give you an array of field names.
The schema.obj
also specifies the field type.
Upvotes: 0
Reputation: 1795
you can get the type of property of a subdoc by
[Collection].schema.paths.[sub-doc].schema.paths.[sub-doc-property].instance // it will give dataytpe
you can nest it as how many nested sub-doc you have
for your collection you can use
ThisCollection.schema.paths.location_details.schema.paths.location_name.instance // String
_
/**
* @param {Object} coll - Collection
* @param {string} props - properties, eg. "abc", "abc.xyz", upto n number of nested dot notation
*/
function getType(coll, props) {
return props.split('.').reduce(function (p, n, index, array) {
if (index < array.length - 1) {
return p.schema.paths[n];
}
return p.schema.paths[n].instance;
}, coll);
}
var type = getType(ThisCollection, "location_details.location_name");
console.log(type); // String
Upvotes: 1
Reputation: 312139
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] }
Upvotes: 4
Reputation: 103475
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);
});
Upvotes: 1