Nie jestem zbyt zaznajomiony z JavaScriptem i oszałamiającym, ponieważ nie mogę dodać nowej właściwości do obiektu, który został pobrany z bazy danych przy użyciu nazw ORM Sequelize.js.
Aby tego uniknąć, używam tego hacka:
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);
});
Więc jaki jest normalny sposób dodawania nowych właściwości do obiektu.
Jeśli to pomoże, używam sequelize-postgres w wersji 2.0.x.
upd. console.log (węzeł):
{ 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] } } }
Myślę, że teraz myślisz, że będzie to: „Ok, to proste, po prostu dodaj swoją właściwość do dataValues”.
node.selectedValues.sensors = sensors;
node.dataValues.sensors = sensors;
Dodam te linie i to nie działa
node.js
sequelize.js
Rusłan
źródło
źródło
node
nie może być przedmiotem tradycyjnym. Może to jest bufor? Co mówiconsole.log(node);
przed twoją linią tricków?Odpowiedzi:
Jeśli dobrze rozumiem, chcesz dodać
sensors
kolekcję do plikunode
. Jeśli masz odwzorowanie między oboma modelami, możesz użyćinclude
funkcji wyjaśnionej tutaj lub metodyvalues
pobierającej zdefiniowanej w każdej instancji. Możesz znaleźć odpowiednie dokumenty tutaj .Ten ostatni może być używany w następujący sposób:
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); });
Jest szansa, że
nodedata.sensors = sensors
to też się uda.źródło
możesz użyć opcji zapytania,
{raw: true}
aby zwrócić nieprzetworzony wynik. Twoje zapytanie powinno wyglądać następująco:db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw: true, })
również jeśli masz z
include
tym skojarzenia , zostanie spłaszczony. Możemy więc użyć innego parametrunest:true
db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw: true, nest: true, })
źródło
nest: true
razem zraw: true
.raw:true
masz pomysł, jak przekazać to ustawienie globalne, więc nie ma potrzeby przekazywania go do każdego zapytania? DziękiDla tych, którzy ostatnio
.values
napotkali to pytanie, jest on przestarzały od wersji Sequelize 3.0.0. Użyj.get()
zamiast tego, aby uzyskać zwykły obiekt javascript. Więc powyższy kod zmieniłby się na:var nodedata = node.get({ plain: true });
Sekwencjonuj dokumenty tutaj
źródło
.get()
nie spowoduje konwersji dołączonych skojarzeń,.get({ plain: true })
zamiast tego użyj . Dzięki za wspomnienie sugestii od doktorów.raw: true
Najlepszym i najprostszym sposobem jest:
Po prostu użyj domyślnego sposobu z Sequelize
db.Sensors.findAll({ where: { nodeid: node.nodeid }, raw : true // <----------- Magic is here }).success(function (sensors) { console.log(sensors); });
Dla zagnieżdżonego wyniku / jeśli mamy uwzględniony model, W najnowszej wersji 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); });
źródło
sensors
z tablicą podrzędnąsomeModel
, otrzymaszarray
ofsensors
z jednymsomeModel
w każdym.Jak zauważa CharlesA w swojej odpowiedzi,
.values()
jest technicznie przestarzała , chociaż fakt ten nie jest wyraźnie odnotowany w dokumentacji . Jeśli nie chcesz używać{ raw: true }
w zapytaniu, preferowanym podejściem jest wywołanie.get()
wyników..get()
jednakże jest metodą instancji, a nie tablicy. Jak wspomniano w powiązanym problemie powyżej, Sequelize zwraca natywne tablice obiektów instancji (a opiekunowie nie planują tego zmieniać), więc musisz samodzielnie iterować po tablicy:db.Sensors.findAll({ where: { nodeid: node.nodeid } }).success((sensors) => { const nodeData = sensors.map((node) => node.get({ plain: true })); });
źródło
Możesz użyć funkcji mapy. to działa dla mnie.
db.Sensors .findAll({ where: { nodeid: node.nodeid } }) .map(el => el.get({ plain: true })) .then((rows)=>{ response.json( rows ) });
źródło
results = results.map(el => el.get({ plain: true }))
Oto, czego używam, aby uzyskać zwykły obiekt odpowiedzi z wartościami niezredagowanymi i wszystkimi zagnieżdżonymi skojarzeniami z
sequelize
zapytania v4.Ze zwykłym JavaScriptem (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); };
Z lodaszkiem (trochę bardziej zwięźle):
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); };
Użycie :
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', // }] // }] // }]
źródło
toJSON
działało dobrze, więc nie potrzebowałem niestandardowej implementacji, takiej jak Twoja.Znalazłem rozwiązanie, które działa dobrze w przypadku modelu zagnieżdżonego i tablicy przy użyciu natywnych funkcji 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
źródło
Dla zagnieżdżonego zwykłego tekstu JSON
db.model.findAll({ raw : true , nest : true })
źródło