web-dev-qa-db-ja.com

JSONデータ型の逐次化

モデルを次のように定義しました

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

  return MyModel;
};

私はそれを使ってクエリします

MyModel.findAll().then(myModels => ...);

ただし、クエリ結果のdataフィールドは文字列であり、JSONオブジェクトではありません。どうすれば修正できますか?

11
MikkoP

まだサポートされていません 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 でも見つけました。ゲッターとセッターを使用したくない場合は、試してみることができます。

16
Jalal

Jalalの答えは素晴らしかったが、少し微調整しないとうまくいかなかった。これが私のために働いたものです:

First:必要なフィールドをタイプTEXTとして追加する移行を作成します。例-addressというフィールドをStoresテーブルに追加します。

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

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

Next:モデル内で、フィールドとデータ型のリスト(オブジェクト)にゲッターとセッターを含むフィールドを追加します。

_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のやり方)。
2
Ira Herman

MySQLではJSONデータ型はサポートされていません。

こちらのドキュメントをご覧ください http://docs.sequelizejs.com/en/v3/docs/models-definition/#data-types

回避策は、クエリ時にテキストを使用して文字列化/解析することです。

1
redeye

最も簡単な解決策は、この 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);
    });
0
Hamza Hmem

JSONがsequelizeでサポートされるようになったので、getterとsetterを使用する必要はありません。参照 sequelize api

0
sharad shetty