2014-02-22 4 views
38

ORM 이름 Sequelize.js를 사용하여 데이터베이스에서 가져온 개체에 새 속성을 추가 할 수 없기 때문에 자바 스크립트에 익숙하지 않아서 놀랍습니다. 그래서Sequelize, 일반 개체로 엔티티 변환

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; 

나는이 라인을 추가하고, 당신이 바로, 당신은 nodesensors 모음을 추가 할 수있는 경우이

+0

'노드 '~해야합니다. 전통적 대상이 되라. 아마도 그것은 완충제인가? 트릭 라인이 나오기 전에'console.log (node);'는 무엇을 말합니까? –

+0

업데이트 소식을 참조하십시오. – IRus

답변

20

을 작동하지 않습니다. 두 모델간에 매핑이있는 경우 include 기능 explained here 또는 모든 인스턴스에 대해 values 게터를 정의 할 수 있습니다. 문서 for that here을 찾을 수 있습니다.

후자는 다음과 같이 사용할 수 있습니다 nodedata.sensors = sensors뿐만 아니라 일할 수 있다는 가능성이

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

있습니다.

+2

고마워요, 내가 필요한 모든 것 : node.values ​​:) – IRus

+0

이것은 나를 위해 일했습니다! 단! – hellojebus

+2

문서에 대한 링크가 없습니다. – Rastalamm

65

쿼리 옵션 {raw: true}을 사용하여 원시 결과를 반환 할 수 있습니다. 좋아한다 귀하의 질의는 다음과 같습니다

최근에이 질문 건너 오는 사람들을 위해
db.Sensors.findAll({ 
    where: { 
    nodeid: node.nodeid 
    }, 
    raw: true, 
}) 
+0

멋지 네요, 고마워요! – IRus

+6

"raw : true"는 연결된 모델에 의해 주입 된 배열을 어떻게 든 평평하게합니다. 지금까지 발견 된 유일한 해결 방법은 configs = JSON.parse (JSON.stringify (configs))입니다. –

+0

허용되는 답변보다 간단하고 나은 접근 방법입니다. 고마워요 – pyprism

53

.values는 Sequelize 3.0.0로 사용되지 않습니다. 대신 .get()을 사용하여 일반 자바 스크립트 개체를 가져옵니다. CharlesA는 그의 대답에 지적으로이 사실을 명시 적으로 docs에 기록되지하지만 .values()technically deprecated이며, 여기

+2

내가 틀렸다면 정정 해주세요.하지만 행 배열로 작동하지 않을 것이라고 생각하십니까? 예를 들어 .findAndcount를 사용하면 결과 행을 .map하고 필요한 항목을 얻기 위해 .get을 각각 반환해야합니다. – backdesk

+0

아마도 JSON.stringify 또는 res.json을 실행하는 것이 더 쉬울 것입니다 (Express 내에서 작업하는 경우). – backdesk

+0

@backdesk - 배열에서 시도하지 않았습니다.하지만 [docs] (http://docs.sequelizejs.com/en/latest/docs/instances/#values-of-an-instance)에서와 같이 보입니다. 똑같은 것을 돌려 주어야합니다. – CharlesA

9

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

Sequelize docs : 그래서 위의 코드로 변경합니다. 쿼리에 { raw: true }을 사용하지 않으려면 .get()을 호출하는 것이 좋습니다.

.get() 그러나 배열의 인스턴스가 아니라 방법입니다. 위의 링크 된 문제에 언급 한 바와 같이, Sequelize는 인스턴스 객체의 기본 배열을 반환한다 (그리고 테이너는 변경에 대한 계획이없는), 그래서 당신은 배열 자신을 반복해야한다 : 나는 해결책을 발견

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

기본 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 
3

최고의하기의 간단한 방법은 다음과 같습니다 원시 결과를 반환 :

그냥 [options.raw] Sequelize

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

에서 기본 방법을 사용합니다. 자세한 정보는 sequelize.query를 참조하십시오.

2

다음은 비 문자형 값이 포함 된 일반 응답 객체와 모든 중첩 된 연관을 sequelize v4 쿼리로 가져 오기 위해 사용하는 것입니다.

일반 자바 스크립트 (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', 
//  }] 
// }] 
// }]