web-dev-qa-db-fra.com

Sequelize JSON type de données

J'ai défini un modèle comme

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

  return MyModel;
};

Je l'interroge en utilisant

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

Cependant, le champ data dans le résultat de la requête est une chaîne, pas un objet JSON. Comment je le répare?

11
MikkoP

Ce n'est pas encore pris en charge MySQL JSON Data Type # 4727 . Mais vous pouvez faire quelque chose comme ça:

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

J'ai également trouvé ce paquet sur github sequelize-json vous pouvez l'essayer si vous ne voulez pas utiliser les getters et les setters.

16
Jalal

La réponse de Jalal a été excellente, mais n'a pas fonctionné pour moi à moins que je l'aie légèrement modifiée. Voici ce qui a fonctionné pour moi:

First: créer une migration qui ajoute le champ souhaité en tant que type TEXT. exemple - Je veux ajouter un champ appelé address à la table Stores:

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

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

Next: A l'intérieur de votre modèle, ajoutez le champ avec des getters et setters à votre liste (objet) de champs et de types de données:

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

Donc, mon modèle entier ressemble à ceci:

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

Maintenant vous pouvez créer et récupérer des enregistrements comme vous le feriez avec un champ de type JSON dans la base de données.

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

Quelques notes:

Dans les blocs de code ci-dessus ...

  • Remplacez address par le nom de champ que vous souhaitez utiliser.
  • Remplacez Stores par le nom de votre modèle/table.
  • J'ai ajouté return sur le setter, sinon il faisait une erreur en essayant de créer un nouvel enregistrement (comme Jalal l'a).
2
Ira Herman

Les types de données JSON ne sont pas pris en charge pour MySQL.

Voir les documents ici http://docs.sequelizejs.com/en/v3/docs/models-definition/#data-types

Une solution de contournement pourrait être d'utiliser du texte et de stringify/parse lors de l'interrogation

1
redeye

La solution la plus simple consiste à utiliser cette petite bibliothèque appelée sequelize-json

Créez une base de données et un schéma:

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

Notez les paramètres de JsonField, vous passez votre instance Sequelize, le nom du modèle et le nom du champ. Un peu gênant, mais cela est nécessaire pour ajouter les crochets appropriés à l'instance de modèle.

Maintenant, vous pouvez toujours traiter ce champ comme un objet 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

Plus besoin d'utiliser des getters et setters car JSON est maintenant supporté par sequelize.See sequelize api

0
sharad shetty