私は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を使用します。
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] } } }
次に、あなたはどう思うだろうと思います。「わかりました。簡単です。dataValuesにプロパティを追加するだけです。」
node.selectedValues.sensors = sensors;
node.dataValues.sensors = sensors;
私はこの行を追加し、これは動作しません
よろしければ、sensors
コレクションをnode
に追加します。両方のモデル間にマッピングがある場合は、include
機能を使用できます ここで説明 またはすべてのインスタンスで定義されたvalues
ゲッター。ドキュメントを見つけることができます そのために 。
後者は次のように使用できます。
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で非推奨になりました。代わりに.get()
を使用して、プレーンなJavaScriptオブジェクトを取得します。したがって、上記のコードは次のように変更されます。
var nodedata = node.get({ plain: true });
Sequelize docs here
CharlesAが彼の答えで述べているように、.values()
は 技術的に非推奨 ですが、この事実は docs には明示的に記載されていません。クエリで{ 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 // <----------- Magic is here
}).success(function (sensors) {
console.log(sensors);
});
注:[options.raw]:生の結果を返します。詳細については、sequelize.queryを参照してください。
ネストされた結果/モデルを含める場合、最新バージョンの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);
});
以下は、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',
// }]
// }]
// }]
マップ機能を使用できます。これは私のために働いています。
db.Sensors
.findAll({
where: { nodeid: node.nodeid }
})
.map(el => el.get({ plain: true }))
.then((rows)=>{
response.json( rows )
});
私は、ネイティブ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