Não estou muito familiarizado com javascript, e surpreendente, porque não consigo adicionar uma nova propriedade, ao objeto, que buscou do banco de dados usando nomes ORM Sequelize.js.
Para evitar isso, uso este 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);
});
Então, qual é a maneira normal de adicionar novas propriedades ao objeto.
Se puder ajudar, eu uso sequelize-postgres versão 2.0.x.
atualiz. console.log (nó):
{ 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] } } }
Acho que a seguir, o que você acha que será: "Ok, isso é fácil, basta adicionar sua propriedade a dataValues."
node.selectedValues.sensors = sensors;
node.dataValues.sensors = sensors;
Eu adiciono essas linhas, e isso não funciona
node.js
sequelize.js
Ruslan
fonte
fonte
node
não deve ser um objeto tradicional. Talvez seja um Buffer? O queconsole.log(node);
antes de sua linha de truque diz?Respostas:
Se entendi bem, você deseja adicionar a
sensors
coleção aonode
. Se você tiver um mapeamento entre os dois modelos, poderá usar ainclude
funcionalidade explicada aqui ou ovalues
getter definido em cada instância. Você pode encontrar os documentos para isso aqui .O último pode ser usado assim:
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); });
Há uma chance de que
nodedata.sensors = sensors
também funcione.fonte
você pode usar as opções de consulta
{raw: true}
para retornar o resultado bruto. Sua consulta deve ser a seguinte:db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw: true, })
também se você tiver associações com
include
isso, fica achatado. Então, podemos usar outro parâmetronest:true
db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw: true, nest: true, })
fonte
nest: true
junto comraw: true
.raw:true
como uma configuração global, então não há necessidade de passar para todas as consultas? ObrigadoPara aqueles que se
.values
depararam com esta questão mais recentemente, está obsoleto a partir do Sequelize 3.0.0. Use.get()
para obter o objeto javascript simples. Portanto, o código acima mudaria para:var nodedata = node.get({ plain: true });
Sequelize os documentos aqui
fonte
.get()
não converterá associações incluídas, use em seu.get({ plain: true })
lugar. Obrigado por mencionar a sugestão dos documentos.raw: true
A melhor e mais simples maneira de fazer é:
Basta usar a forma padrão do Sequelize
db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw : true // <----------- Magic is here }).success(function (sensors) { console.log(sensors); });
Para o resultado aninhado / se tivermos modelo de inclusão, na versão mais recente do 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); });
fonte
sensors
com uma matriz de filhosomeModel
, você obterá umarray
desensors
com umsomeModel
em cada.Como CharlesA observa em sua resposta,
.values()
está tecnicamente obsoleto , embora esse fato não seja explicitamente mencionado nos documentos . Se você não quiser usar{ raw: true }
na consulta, a abordagem preferencial é chamar.get()
os resultados..get()
, entretanto, é um método de uma instância, não de uma matriz. Conforme observado no problema vinculado acima, Sequelize retorna arrays nativos de objetos de instância (e os mantenedores não planejam mudar isso), então você tem que iterar por meio do array você mesmo:db.Sensors.findAll({ where: { nodeid: node.nodeid } }).success((sensors) => { const nodeData = sensors.map((node) => node.get({ plain: true })); });
fonte
você pode usar a função de mapa. isso funcionou para mim.
db.Sensors .findAll({ where: { nodeid: node.nodeid } }) .map(el => el.get({ plain: true })) .then((rows)=>{ response.json( rows ) });
fonte
results = results.map(el => el.get({ plain: true }))
Eu encontrei uma solução que funciona bem para o modelo aninhado e array usando funções 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
fonte
Aqui está o que estou usando para obter o objeto de resposta simples com valores não stringificados e todas as associações aninhadas da
sequelize
consulta v4.Com JavaScript simples (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); };
Com lodash (um pouco mais 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', // }] // }] // }]
fonte
Para texto simples JSON aninhado
db.model.findAll({ raw : true , nest : true })
fonte