I\'m not very familiar with javascript, and stunning, because i can\'t add new property, to object, that fetched from database using ORM names Sequelize.js.
To avoid
Here's what I'm using to get plain response object with non-stringified values and all nested associations from sequelize
v4 query.
With plain JavaScript (ES2015+):
const toPlain = response => {
const flattenDataValues = ({ dataValues }) => {
const flattenedObject = {};
Object.keys(dataValues).forEach(key => {
const dataValue = dataValues[key];
if (
Array.isArray(dataValue) &&
dataValue[0] &&
dataValue[0].dataValues &&
typeof dataValue[0].dataValues === 'object'
) {
flattenedObject[key] = dataValues[key].map(flattenDataValues);
} else if (dataValue && dataValue.dataValues && typeof dataValue.dataValues === 'object') {
flattenedObject[key] = flattenDataValues(dataValues[key]);
} else {
flattenedObject[key] = dataValues[key];
}
});
return flattenedObject;
};
return Array.isArray(response) ? response.map(flattenDataValues) : flattenDataValues(response);
};
With lodash (a bit more concise):
const toPlain = response => {
const flattenDataValues = ({ dataValues }) =>
_.mapValues(dataValues, value => (
_.isArray(value) && _.isObject(value[0]) && _.isObject(value[0].dataValues)
? _.map(value, flattenDataValues)
: _.isObject(value) && _.isObject(value.dataValues)
? flattenDataValues(value)
: value
));
return _.isArray(response) ? _.map(response, flattenDataValues) : flattenDataValues(response);
};
Usage:
const res = await User.findAll({
include: [{
model: Company,
as: 'companies',
include: [{
model: Member,
as: 'member',
}],
}],
});
const plain = toPlain(res);
// 'plain' now contains simple db object without any getters/setters with following structure:
// [{
// id: 123,
// name: 'John',
// companies: [{
// id: 234,
// name: 'Google',
// members: [{
// id: 345,
// name: 'Paul',
// }]
// }]
// }]
I have found a solution that works fine for nested model and array using native JavaScript functions.
var results = [{},{},...]; //your result data returned from sequelize query
var jsonString = JSON.stringify(results); //convert to string to remove the sequelize specific meta data
var obj = JSON.parse(jsonString); //to make plain json
// do whatever you want to do with obj as plain json
For those coming across this question more recently, .values
is deprecated as of Sequelize 3.0.0. Use .get()
instead to get the plain javascript object. So the above code would change to:
var nodedata = node.get({ plain: true });
Sequelize docs here
you can use map function. this is worked for me.
db.Sensors
.findAll({
where: { nodeid: node.nodeid }
})
.map(el => el.get({ plain: true }))
.then((rows)=>{
response.json( rows )
});
Best and the simple way of doing is :
Just use the default way from Sequelize
db.Sensors.findAll({
where: {
nodeid: node.nodeid
},
raw : true // <----------- Magic is here
}).success(function (sensors) {
console.log(sensors);
});
Note : [options.raw] : Return raw result. See sequelize.query for more information.
For the nested result/if we have include model , In latest version of sequlize ,
db.Sensors.findAll({
where: {
nodeid: node.nodeid
},
include : [
{ model : someModel }
]
raw : true , // <----------- Magic is here
nest : true // <----------- Magic is here
}).success(function (sensors) {
console.log(sensors);
});
If I get you right, you want to add the sensors
collection to the node
. If you have a mapping between both models you can either use the include
functionality explained here or the values
getter defined on every instance. You can find the docs for that here.
The latter can be used like this:
db.Sensors.findAll({
where: {
nodeid: node.nodeid
}
}).success(function (sensors) {
var nodedata = node.values;
nodedata.sensors = sensors.map(function(sensor){ return sensor.values });
// or
nodedata.sensors = sensors.map(function(sensor){ return sensor.toJSON() });
nodesensors.push(nodedata);
response.json(nodesensors);
});
There is chance that nodedata.sensors = sensors
could work as well.