将实体转换为普通对象

我不是很熟悉javascript,而且令人惊叹,因为我无法添加新的属性,使用ORM名称Sequelize.js从数据库中获取对象。

为了避免这种情况,我使用这个黑客:

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); }); 

那么,通常以什么方式向对象添加新的属性。

如果可以帮助,我使用sequelize-postgres 2.0.x版。

UPD。 的console.log(节点):

 { 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] } } } 

我想下一步,你会怎么想:“好的,这很简单,只需要将你的属性添加到dataValues。”

 node.selectedValues.sensors = sensors; node.dataValues.sensors = sensors; 

我添加这行,这是行不通的

如果我找不到,则需要将sensors集合添加到node 。 如果两个模型之间有映射关系,则可以使用这里介绍的includefunction或每个实例定义的values getter。 你可以在这里find这个文档。

后者可以这样使用:

 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); }); 

nodedata.sensors = sensors也有可能工作。

您可以使用查询选项{raw: true}来返回原始结果。 你的查询应该如下所示:

 db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw: true, }) 

对于最近遇到这个问题的人来说, .values在Sequelize 3.0.0中.values被弃用了。 使用.get()来获得普通的javascript对象。 所以上面的代码会变成:

 var nodedata = node.get({ plain: true }); 

在此处将文档encryption

正如CharlesA在他的回答中所指出的那样, .values()在技术上被弃用 ,尽pipe这个事实在文档中没有明确指出。 如果您不想在查询中使用{ raw: true } ,首选方法是对结果调用.get()

.get() ,但是,是一个实例的方法,而不是一个数组。 正如上面的链接问题所述,Sequelize返回实例对象的本地数组(并且维护者不打算改变它),所以你必须自己遍历数组:

 db.Sensors.findAll({ where: { nodeid: node.nodeid } }).success((sensors) => { const nodeData = sensors.map((node) => node.get({ plain: true })); }); 

最好的和简单的做法是:

只需使用Sequelize的默认方式

 db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw : true }).success(function (sensors) { console.log(sensors); }); 

[options.raw]:返回原始结果。 有关更多信息,请参见sequelize.query。

我发现了一个解决scheme,使用原生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 

以下是我用来获取非string值的普通响应对象以及来自sequelize v4查询的所有嵌套关联。

普通的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); }; 

lodash (更简洁一点):

 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); }; 

用法

 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', // }] // }] // }] 

当你尝试添加一个属性时,你会得到什么错误?

我知道很多人喜欢用lodash的分配方法来达到这些目的。 详细信息: Lodash .extend()/ .assign()和.merge()之间的区别