Je ne suis pas très familier avec javascript et stupéfiant, parce que je ne peux pas ajouter de nouvelle propriété à un objet extrait de la base de données à l'aide des noms ORM Sequelize.js.
Pour éviter cela, j'utilise ce 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);
});
Alors, comment normalement ajouter de nouvelles propriétés à un objet?.
Si cela peut aider, j'utilise la version 2.0.x de Sequelize-postgres.
pd. 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] } } }
Je pense ensuite ce que vous pensez: "Ok, c'est facile, ajoutez simplement votre propriété à dataValues."
node.selectedValues.sensors = sensors;
node.dataValues.sensors = sensors;
J'ajoute ces lignes, et ça ne marche pas
Si je vous comprends bien, vous souhaitez ajouter la collection sensors
à la collection node
. Si vous avez un mappage entre les deux modèles, vous pouvez utiliser la fonctionnalité include
expliquée ici ou le values
getter défini. sur chaque instance. Vous pouvez trouver la documentation pour cela ici .
Ce dernier peut être utilisé comme ceci:
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);
});
Il y a une chance que nodedata.sensors = sensors
pourrait également fonctionner.
vous pouvez utiliser les options de requête {raw: true}
pour renvoyer le résultat brut. Votre requête devrait ressembler à ceci:
db.Sensors.findAll({
where: {
nodeid: node.nodeid
},
raw: true,
})
Pour ceux qui rencontrent cette question plus récemment, .values
Est obsolète à partir de Sequelize 3.0.0. Utilisez .get()
à la place pour obtenir l'objet javascript simple. Donc, le code ci-dessus deviendrait:
var nodedata = node.get({ plain: true });
Sequelize docs ici
Comme CharlesA le note dans sa réponse, .values()
est techniquement déconseillé , bien que ce fait ne soit pas explicitement mentionné dans les docs . Si vous ne souhaitez pas utiliser { raw: true }
Dans la requête, l'approche recommandée consiste à appeler .get()
sur les résultats.
.get()
, cependant, est une méthode d'instance et non de tableau. Comme indiqué dans le problème lié ci-dessus, Sequelize renvoie des tableaux natifs d'objets d'instance (et les responsables ne prévoient pas de le changer). Vous devez donc parcourir le tableau vous-même:
db.Sensors.findAll({
where: {
nodeid: node.nodeid
}
}).success((sensors) => {
const nodeData = sensors.map((node) => node.get({ plain: true }));
});
Le meilleur moyen de faire est:
Il suffit d'utiliser le chemin par défaut de Sequelize
db.Sensors.findAll({
where: {
nodeid: node.nodeid
},
raw : true // <----------- Magic is here
}).success(function (sensors) {
console.log(sensors);
});
Remarque: [options.raw]: renvoie le résultat brut. Voir sequelize.query pour plus d'informations.
Pour le résultat imbriqué/si nous avons un modèle d'inclusion, dans la dernière version 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);
});
Voici ce que j'utilise pour obtenir un objet de réponse simple avec des valeurs non stringifiées et toutes les associations imbriquées à partir de la requête sequelize
v4.
Avec 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);
};
Avec lodash (un peu plus concis):
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);
};
sage:
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',
// }]
// }]
// }]
vous pouvez utiliser la fonction map. cela a fonctionné pour moi.
db.Sensors
.findAll({
where: { nodeid: node.nodeid }
})
.map(el => el.get({ plain: true }))
.then((rows)=>{
response.json( rows )
});
J'ai trouvé une solution qui fonctionne bien pour les modèles et les tableaux imbriqués à l'aide de fonctions JavaScript natives.
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