I\'m using Mongoose.js to create models with schemas.
I have a list of models (many) and at times I\'d like to get the attributes/keys that make up a particular mo
Yes, it is possible.
Each schema has a paths property, that looks somewhat like this (this is an example of my code):
paths: {
number: [Object],
'name.first': [Object],
'name.last': [Object],
ssn: [Object],
birthday: [Object],
'job.company': [Object],
'job.position': [Object],
'address.city': [Object],
'address.state': [Object],
'address.country': [Object],
'address.street': [Object],
'address.number': [Object],
'address.zip': [Object],
email: [Object],
phones: [Object],
tags: [Object],
createdBy: [Object],
createdAt: [Object],
updatedBy: [Object],
updatedAt: [Object],
meta: [Object],
_id: [Object],
__v: [Object]
}
You can access this through an model too. It's under Model.schema.paths.
You can use Schema.prototype.obj that returns the original object passed to the schema constructor. and you can use it in a utility function to build the object you're going to save.
import Todo from './todoModel'
import { validationResult } from 'express-validator'
const buildObject = (body) => {
const data = {};
const keys = Object.keys(Todo.schema.obj);
keys.map(key => { if (body.hasOwnProperty(key)) data[key] = body[key] })
return data;
}
const create = async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.json(errors);
let toBeSaved = buildObject(req.body);
const todo = new Todo(toBeSaved);
const savedTodo = await todo.save();
if (savedTodo) return res.json(savedTodo);
return res.json({ 'sanitized': keys })
} catch (error) {
res.json({ error })
}
}
another way is to to not call the buildObject function and add it in two lines but you will write every key you want to save
let { title, description } = req.body;
let toBeSaved = { title, description };
Using ES6 shorthand property names
Just insert the field name you like to get.
let fieldName = 'birthday'
console.log(mySchema.schema.paths[fieldName].instance);
Don't have enough rep to comment, but this also spits out a list and loops through all of the schema types.
mySchema.schema.eachPath(function(path) {
console.log(path);
});
should print out:
number
name.first
name.last
ssn
birthday
job.company
job.position
address.city
address.state
address.country
address.street
address.number
address.zip
email
phones
tags
createdBy
createdAt
updatedBy
updatedAt
meta
_id
__v
Or you could get all Attributes as an Array like this:
var props = Object.keys(mySchema.schema.paths);
Solution for lodash, function which picked all schema properties, excluding specified
_.mixin({ pickSchema: function (model, excluded) {
var fields = [];
model.schema.eachPath(function (path) {
_.isArray(excluded) ? excluded.indexOf(path) < 0 ? fields.push(path) : false : path === excluded ? false : fields.push(path);
});
return fields;
}
});
_.pickSchema(User, '_id'); // will return all fields except _id
_.pick(req.body, _.pickSchema(User, ['_id', 'createdAt', 'hidden'])) // all except specified properties
read more here https://gist.github.com/styopdev/95f3fed98ce3ebaedf5c
In case you want to have all property values (including nested and populated properties), just use toObject() method:
let modelAttributes = null;
SomeModel.findById('someId').populate('child.name').exec().then((result) => {
modelAttributes = result.toObject();
console.log(modelAttributes);
});
The output would be:
{
id: 'someId',
name: 'someName',
child: {
name: 'someChildName'
}
...
}