Reputation: 14620
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 this, i use this hack:
db.Sensors.findAll({
where: {
nodeid: node.nodeid
}
}).success(function (sensors) {
var nodedata = JSON.parse(JSON.stringify(node)); // this is my trick
nodedata.sensors = sensors;
nodesensors.push(nodedata);
response.json(nodesensors);
});
So, what normally way to add new properties to object.
If it can help, i use sequelize-postgres version 2.0.x.
upd. console.log(node):
{ dataValues:
{ nodeid: 'NodeId',
name: 'NameHere',
altname: 'Test9',
longname: '',
latitude: 30,
longitude: -10,
networkid: 'NetworkId',
farmid: '5',
lastheard: Mon Dec 09 2013 04:04:40 GMT+0300 (FET),
id: 9,
createdAt: Tue Dec 03 2013 01:29:09 GMT+0300 (FET),
updatedAt: Sun Feb 23 2014 01:07:14 GMT+0300 (FET) },
__options:
{ timestamps: true,
createdAt: 'createdAt',
updatedAt: 'updatedAt',
deletedAt: 'deletedAt',
touchedAt: 'touchedAt',
instanceMethods: {},
classMethods: {},
validate: {},
freezeTableName: false,
underscored: false,
syncOnAssociation: true,
paranoid: false,
whereCollection: { farmid: 5, networkid: 'NetworkId' },
schema: null,
schemaDelimiter: '',
language: 'en',
defaultScope: null,
scopes: null,
hooks: { beforeCreate: [], afterCreate: [] },
omitNull: false,
hasPrimaryKeys: false },
hasPrimaryKeys: false,
selectedValues:
{ nodeid: 'NodeId',
name: 'NameHere',
longname: '',
latitude: 30,
longitude: -110,
networkid: 'NetworkId',
farmid: '5',
lastheard: Mon Dec 09 2013 04:04:40 GMT+0300 (FET),
id: 9,
createdAt: Tue Dec 03 2013 01:29:09 GMT+0300 (FET),
updatedAt: Sun Feb 23 2014 01:07:14 GMT+0300 (FET),
altname: 'Test9' },
__eagerlyLoadedAssociations: [],
isDirty: false,
isNewRecord: false,
daoFactoryName: 'Nodes',
daoFactory:
{ options:
{ timestamps: true,
createdAt: 'createdAt',
updatedAt: 'updatedAt',
deletedAt: 'deletedAt',
touchedAt: 'touchedAt',
instanceMethods: {},
classMethods: {},
validate: {},
freezeTableName: false,
underscored: false,
syncOnAssociation: true,
paranoid: false,
whereCollection: [Object],
schema: null,
schemaDelimiter: '',
language: 'en',
defaultScope: null,
scopes: null,
hooks: [Object],
omitNull: false,
hasPrimaryKeys: false },
name: 'Nodes',
tableName: 'Nodes',
rawAttributes:
{ nodeid: [Object],
name: [Object],
altname: [Object],
longname: [Object],
latitude: [Object],
longitude: [Object],
networkid: [Object],
farmid: [Object],
lastheard: [Object],
id: [Object],
createdAt: [Object],
updatedAt: [Object] },
daoFactoryManager: { daos: [Object], sequelize: [Object] },
associations: {},
scopeObj: {},
primaryKeys: {},
primaryKeyCount: 0,
hasPrimaryKeys: false,
autoIncrementField: 'id',
DAO: { [Function] super_: [Function] } } }
I think next, what you think will be: "Ok, that is easy, just add your property to dataValues."
node.selectedValues.sensors = sensors;
node.dataValues.sensors = sensors;
I add this lines, and this don't work
Upvotes: 151
Views: 244720
Reputation: 4419
you can use the query options {raw: true}
to return the raw result. Your query should like follows:
db.Sensors.findAll({
where: {
nodeid: node.nodeid
},
raw: true,
})
also if you have associations with include
that gets flattened. So, we can use another parameter nest:true
db.Sensors.findAll({
where: {
nodeid: node.nodeid
},
raw: true,
nest: true,
})
Upvotes: 245
Reputation: 2234
For plain objects
db.model.findAll({
raw : true ,
nest : true
})
Upvotes: 7
Reputation: 91
I use my own model mixin for handy responses
const camelcaseKeys = require('camelcase-keys');
const initMixins = Sequelize => {
// Convert model to plain object and camelcase keys for response
Sequelize.Model.prototype.toPlainObject = function({ camelcase = false } = {}) {
const plain = this.get({ plain: true });
if (camelcase) {
return camelcaseKeys(plain, { deep: true });
} else {
return plain;
}
};
};
module.exports = {
initMixins,
};
// usage
const userModel = await UserModel.findOne();
console.log(userModel.toPlainObject());
Upvotes: 2
Reputation: 2402
It's a little late to answer, but in case someone runs across this question and needs a solution...
(Assuming this is in async/await function)
const sensors = JSON.parse(JSON.stringify(await
db.Sensors.findAll({
where: {
nodeid: node.nodeid
}
})))
You can query and return it is a plain object, array of objects, etc...
Upvotes: 3
Reputation: 31
You can also try this if you want to occur for all the queries:
var sequelize = new Sequelize('database', 'username', 'password', {query:{raw:true}})
Visit Setting all queries to raw = true sequelize
Upvotes: 2
Reputation: 1178
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 )
});
Upvotes: 23
Reputation: 58523
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);
});
Upvotes: 60
Reputation: 419
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',
// }]
// }]
// }]
Upvotes: 12
Reputation: 1838
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
Upvotes: 10
Reputation: 702
As CharlesA notes in his answer, .values()
is technically deprecated, though this fact isn't explicitly noted in the docs. If you don't want to use { raw: true }
in the query, the preferred approach is to call .get()
on the results.
.get()
, however, is a method of an instance, not of an array. As noted in the linked issue above, Sequelize returns native arrays of instance objects (and the maintainers don't plan on changing that), so you have to iterate through the array yourself:
db.Sensors.findAll({
where: {
nodeid: node.nodeid
}
}).success((sensors) => {
const nodeData = sensors.map((node) => node.get({ plain: true }));
});
Upvotes: 34
Reputation: 4350
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
Upvotes: 152
Reputation: 6231
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.
Upvotes: 47