node.js Sequelize,将实体转换为普通对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21961818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 16:54:46  来源:igfitidea点击:

Sequelize, convert entity to plain object

node.jssequelize.js

提问by Ruslan

I'm not very familiar with javascript, and stunning, because i can't add new property, to object, that fetched from database using ORM names Sequelize.js.

我对 javascript 不是很熟悉,而且令人惊叹,因为我无法向使用 ORM 名称 Sequelize.js 从数据库中获取的对象添加新属性。

To avoid this, i use this hack:

为了避免这种情况,我使用了这个 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);
});

So, what normally way to add new properties to object.

那么,通常如何向对象添加新属性。

If it can help, i use sequelize-postgres version 2.0.x.

如果有帮助,我使用 sequelize-postgres 2.0.x 版。

upd. 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] } } }

I think next, what you think will be: "Ok, that is easy, just add your property to dataValues."

我想接下来,您的想法将是:“好吧,这很简单,只需将您的属性添加到 dataValues。”

node.selectedValues.sensors = sensors;
node.dataValues.sensors = sensors;

I add this lines, and this don't work

我添加了这一行,但这不起作用

采纳答案by sdepold

If I get you right, you want to add the sensorscollection to the node. If you have a mapping between both models you can either use the includefunctionality explained hereor the valuesgetter defined on every instance. You can find the docs for that here.

如果我没听错,您想将sensors集合添加到node. 如果您有两个模型之间的映射,您可以使用此处解释include功能或在每个实例上定义的getter。您可以在此处找到相关文档。values

The latter can be used like this:

后者可以这样使用:

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

There is chance that nodedata.sensors = sensorscould work as well.

有机会也nodedata.sensors = sensors可以。

回答by lutaoact

you can use the query options {raw: true}to return the raw result. Your query should like follows:

您可以使用查询选项{raw: true}返回原始结果。您的查询应如下所示:

db.Sensors.findAll({
  where: {
    nodeid: node.nodeid
  },
  raw: true,
})

also if you have associations with includethat gets flattened. So, we can use another parameter nest:true

此外,如果您与include它有关联,则会变得扁平。所以,我们可以使用另一个参数nest:true

db.Sensors.findAll({
  where: {
    nodeid: node.nodeid
  },
  raw: true,
  nest: true,
})

回答by CharlesA

For those coming across this question more recently, .valuesis deprecated as of Sequelize 3.0.0. Use .get()instead to get the plain javascript object. So the above code would change to:

对于最近遇到这个问题的人,.values自 Sequelize 3.0.0 起已弃用。使用.get()来获取普通的 javascript 对象。所以上面的代码会变成:

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

Sequelize docshere

续集文档在这里

回答by Vivek Doshi

Best and the simple way of doing is :

最好和最简单的方法是:

Just use the default way from Sequelize

只需使用Sequelize的默认方式

db.Sensors.findAll({
    where: {
        nodeid: node.nodeid
    },
    raw : true // <----------- Magic is here
}).success(function (sensors) {
        console.log(sensors);
});

Note : [options.raw] : Return raw result. See sequelize.query for more information.

注意: [options.raw] :返回原始结果。有关更多信息,请参阅 sequelize.query。



For the nested result/if we have include model , In latest version of sequlize ,

对于嵌套结果/如果我们有包含模型,在最新版本的 sequelize 中,

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

回答by Shane Hughes

As CharlesA notes in his answer, .values()is technically deprecated, though this fact isn't explicitly noted in the docs. If you don't want to use { raw: true }in the query, the preferred approach is to call .get()on the results.

正如他的回答CharlesA笔记,.values()技术上过时,但这一事实并没有明确的说明文档。如果不想{ raw: true }在查询中使用,首选方法是调用.get()结果。

.get(), however, is a method of an instance, not of an array. As noted in the linked issue above, Sequelize returns native arrays of instance objects (and the maintainers don't plan on changing that), so you have to iterate through the array yourself:

.get()但是,是实例的方法,而不是数组的方法。如上面链接的问题所述,Sequelize 返回实例对象的本机数组(维护人员不打算更改它),因此您必须自己遍历数组:

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

回答by nur zazin

you can use map function. this is worked for me.

您可以使用地图功能。这对我有用。

db.Sensors
    .findAll({
        where: { nodeid: node.nodeid }
     })
    .map(el => el.get({ plain: true }))
    .then((rows)=>{
        response.json( rows )
     });

回答by evenfrost

Here's what I'm using to get plain response object with non-stringified values and all nested associations from sequelizev4 query.

这是我用来从sequelizev4 查询中获取具有非字符串化值和所有嵌套关联的普通响应对象的方法。

With plain JavaScript(ES2015+):

使用纯 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);
};

With lodash(a bit more concise):

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

Usage:

用法

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',
//     }]
//   }]
// }]

回答by Suben Saha

I have found a solution that works fine for nested model and array using native JavaScript functions.

我找到了一个解决方案,它适用于使用原生 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

回答by Amr Ibrahim

For nested JSON plain text

对于嵌套的 JSON 纯文本

db.model.findAll({
  raw : true ,
  nest : true
})