No estoy muy familiarizado con javascript, y es sorprendente, porque no puedo agregar una nueva propiedad, al objeto, que se obtuvo de la base de datos usando los nombres ORM Sequelize.js.
Para evitar esto, uso este truco:
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);
});
Entonces, ¿qué forma normalmente de agregar nuevas propiedades al objeto?
Si puede ayudar, uso sequelize-postgres versión 2.0.x.
upd. console.log (nodo):
{ 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] } } }
A continuación, creo que lo que piensa será: "Ok, eso es fácil, simplemente agregue su propiedad a dataValues".
node.selectedValues.sensors = sensors;
node.dataValues.sensors = sensors;
Agrego estas líneas, y esto no funciona
node.js
sequelize.js
Ruslan
fuente
fuente
node
no debe ser un objeto tradicional. ¿Quizás es un búfer? ¿Qué diceconsole.log(node);
antes de tu línea de truco?Respuestas:
Si lo entiendo bien, desea agregar la
sensors
colección al archivonode
. Si tiene un mapeo entre ambos modelos, puede usar lainclude
funcionalidad explicada aquí o elvalues
captador definido en cada instancia. Puedes encontrar los documentos para eso aquí .Este último se puede utilizar así:
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); });
Existe la posibilidad de que eso también
nodedata.sensors = sensors
funcione.fuente
puede utilizar las opciones de consulta
{raw: true}
para devolver el resultado sin procesar. Su consulta debería ser la siguiente:db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw: true, })
también si tiene asociaciones con
include
eso se aplana. Entonces, podemos usar otro parámetronest:true
db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw: true, nest: true, })
fuente
nest: true
junto conraw: true
.raw:true
como una configuración global, por lo que no es necesario pasarlo a cada consulta? GraciasPara aquellos que se encuentren con esta pregunta más recientemente,
.values
está obsoleto a partir de Sequelize 3.0.0. Úselo en su.get()
lugar para obtener el objeto javascript simple. Entonces el código anterior cambiaría a:var nodedata = node.get({ plain: true });
Secuela de documentos aquí
fuente
.get()
no convertirá las asociaciones incluidas, utilice.get({ plain: true })
en su lugar. Gracias por mencionar la sugerencia de los documentos.raw: true
La mejor y más sencilla forma de hacerlo es:
Simplemente use la forma predeterminada de Sequelize
db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw : true // <----------- Magic is here }).success(function (sensors) { console.log(sensors); });
Para el resultado anidado / si hemos incluido el modelo, en la última versión de 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); });
fuente
sensors
con una matriz de elementos secundariossomeModel
, obtendrá unaarray
desensors
con unasomeModel
en cada una.Como señala CharlesA en su respuesta,
.values()
está técnicamente en desuso , aunque este hecho no se menciona explícitamente en los documentos . Si no desea utilizarlo{ raw: true }
en la consulta, el enfoque preferido es consultar.get()
los resultados..get()
, sin embargo, es un método de una instancia, no de una matriz. Como se señaló en el problema vinculado anterior, Sequelize devuelve matrices nativas de objetos de instancia (y los mantenedores no planean cambiar eso), por lo que debe recorrer la matriz usted mismo:db.Sensors.findAll({ where: { nodeid: node.nodeid } }).success((sensors) => { const nodeData = sensors.map((node) => node.get({ plain: true })); });
fuente
puede utilizar la función de mapa. esto funcionó para mí.
db.Sensors .findAll({ where: { nodeid: node.nodeid } }) .map(el => el.get({ plain: true })) .then((rows)=>{ response.json( rows ) });
fuente
results = results.map(el => el.get({ plain: true }))
Encontré una solución que funciona bien para modelos y matrices anidados que utilizan funciones nativas de JavaScript.
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
fuente
Esto es lo que estoy usando para obtener un objeto de respuesta simple con valores sin cadenas y todas las asociaciones anidadas de la
sequelize
consulta v4.Con JavaScript simple (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); };
Con lodash (un poco más conciso):
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); };
Uso :
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', // }] // }] // }]
fuente
Para texto sin formato JSON anidado
db.model.findAll({ raw : true , nest : true })
fuente