Sequelize JSON数据类型

时间:2016-12-22 10:10:30

标签: mysql json node.js sequelize.js

我已将模型定义为

module.exports = function (sequelize, DataTypes) {
  const MyModel = sequelize.define('MyModel', {
    data: {
      type: DataTypes.JSON,
      ...
    },
    ...
  });

  return MyModel;
};

我使用

查询它
MyModel.findAll().then(myModels => ...);

但是,查询结果中的data字段是字符串,而不是JSON对象。我该如何解决?

6 个答案:

答案 0 :(得分:8)

目前尚不支持MySQL JSON Data Type #4727。但你可以这样做:

 module.exports = function (sequelize, DataTypes) {
      const MyModel = sequelize.define('MyModel', {
        data: {
          type: Sequelize.TEXT,
           get: function () {
                return JSON.parse(this.getDataValue('value'));
            },
            set: function (value) {
                this.setDataValue('value', JSON.stringify(value));
            },
    ,
          ...
        },
        ...
      });

      return MyModel;
};

我还在github sequelize-json上找到了这个包你可以尝试一下,如果你不想使用getter和setter。

答案 1 :(得分:3)

由于sequelize现在支持JSON,因此无需使用getter和setter。请参见sequelize api

答案 2 :(得分:1)

MySQL不支持JSON数据类型。

请参阅此处的文档{{3}}

解决方法可能是在查询时使用text和stringify / parse

答案 3 :(得分:1)

Jalal的回答很好,但除非我稍加调整,否则对我不起作用。这是对我有用的东西:

首先:创建一个迁移,该迁移将您想要的字段添加为TEXT类型。 示例-我想向address表中添加一个名为Stores的字段:

module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.addColumn("Stores", "address", Sequelize.TEXT);
  },

  down: (queryInterface, Sequelize) => {
    return queryInterface.removeColumn("Stores", "address");
  }
};

下一步: 在模型内部,将具有getter和setter的字段添加到字段和数据类型的列表(对象)中:

address: {
  type: DataTypes.TEXT,
    get: function() {
      return JSON.parse(this.getDataValue("address"));
    },
    set: function(value) {
      return this.setDataValue("address", JSON.stringify(value));
    }
},

所以我的整个模型如下:

module.exports = (sequelize, DataTypes) => {
  const Store = sequelize.define(
    "Store",
    {
      name: DataTypes.STRING,
      isActive: DataTypes.BOOLEAN,
      address: {
        type: DataTypes.TEXT,
        get: function() {
          return JSON.parse(this.getDataValue("address"));
        },
        set: function(value) {
          return this.setDataValue("address", JSON.stringify(value));
        }
      }
    },
    {}
  );
  Store.associate = function(models) {
    // associations can be defined here
    Store.hasMany(models.Order, {
      foreignKey: "id",
      targetKey: "storeId"
    });
  };
  return Store;
};

现在,您可以创建和检索记录,就像在数据库中使用JSON类型字段一样。

例如:const store = await Store.create({name: "Joe's corner store", address: {address1: "123 test street", city: "Los Angeles", state: "CA"}})

一些注意事项:

在上面的代码块中...

  • 用您要使用的字段名称替换address
  • 用模型/表名称替换Stores
  • 我在设置器上添加了return,否则在尝试创建新记录(Jalal拥有它的方式)时会出错。

答案 4 :(得分:0)

最简单的解决方案是使用名为sequelize-json

的小库

创建数据库和架构:

var Sequelize = require('sequelize'),
  JsonField = require('sequelize-json'),
  db,
  User;

db = new Sequelize('database', 'username', 'password', {
  dialect: 'sqlite',
  logging: false
});

User = db.define('User', {
  username: Sequelize.STRING,
  jsonField: JsonField(db, 'User', 'jsonField')
});

请注意JsonField的参数,您传递了Sequelize实例,模型名称和字段名称。有点笨拙,但这是向模型实例添加适当的钩子所必需的。

现在,您始终可以将该字段视为json对象:

User.create({
      username: 'Scott',
      jsonField: {
        likes: ['running', 'node']
      }
    })
    .then(function(user) {
      user.jsonField.likes.push('tests');
      return user.save();
    })
    .then(function(user) {
      expect(user.jsonField).to.be.a('object');
      expect(user.jsonField.likes).to.have.length(3);
    });
它将与普通的保存命令以及updateAttribute命令一起使用。

答案 5 :(得分:0)

虽然这个问题被标记为 MySQL,但我怀疑一些使用 MariaDB 的人可能会在这里结束,特别是因为 MariaDB 现在在许多地方都是默认的。 MySQL 和 MariaDB 处理 JSON 数据类型的方式有所不同,这就是 sequelize 对这两个 DB 实现不同的原因。

就我而言,我通过将续集显式切换为方言 mariadb 来解决此问题。这要求您安装 mariadb 软件包而不是 mysql2。之后我的 JSON 列被正确解析为一个对象。