Sequelize Model


Modelの定義
import sequelize from 'sequelize'

var Foo = sequelize.define('foo', {
 //           
 flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true},

 //          
 myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW },

 //   allowNull false          NOT NULL ,        null,        
 //                null,        (validations)  
 title: { type: Sequelize.STRING, allowNull: false},

 // unique    boolean,   string.        string
 //      composite unique key.
 uniqueOne: { type: Sequelize.STRING,  unique: 'compositeIndex'},
 uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'}

 // unique     
 someUnique: {type: Sequelize.STRING, unique: true}
 //          
 {someUnique: {type: Sequelize.STRING}},
 {indexes: [{unique: true, fields: ['someUnique']}]}

 //   
 identifier: { type: Sequelize.STRING, primaryKey: true},

 //     
 incrementMe: { type: Sequelize.INTEGER, autoIncrement: true },

 //  MySQL and PG   comments
 hasComment: { type: Sequelize.INTEGER, comment: "I'm a comment!" },

 //     "field"        
 fieldWithUnderscores: { type: Sequelize.STRING, field: "field_with_underscores" },

 //     
 bar_id: {
   type: Sequelize.INTEGER,

   references: {
     // This is a reference to another model
     model: Bar,

     // This is the column name of the referenced model
     key: 'id',

     // This declares when to check the foreign key constraint. PostgreSQL only.
     deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
   }
 }
})
mongooseで定義されているように
import mongoose from 'mongoose'
const Schema = mongoose.Schema,
      ObjectId = Schema.ObjectId

const topicSchema = new Schema({
  title: String,
  content:  String,
  addons: [String],
  date: { type: Date, default: Date.now },
  deleted: { type: Boolean, default: false},
  author: {
    id: ObjectId,
    nickname:  String,
    avatarUrl: String
  },
  location: {type: [Number], index: '2d', sparse: true}, //contain 2 items,long & lat
  genre: {type: String, default: 'public'}
});

export default mongoose.model('topic',topicSchema)

データ型
Sequelize.STRING                      // VARCHAR(255)
Sequelize.STRING(1234)                // VARCHAR(1234)
Sequelize.STRING.BINARY               // VARCHAR BINARY
Sequelize.TEXT                        // TEXT
Sequelize.TEXT('tiny')                // TINYTEXT

Sequelize.INTEGER                     // INTEGER
Sequelize.BIGINT                      // BIGINT
Sequelize.BIGINT(11)                  // BIGINT(11)

Sequelize.FLOAT                       // FLOAT
Sequelize.FLOAT(11)                   // FLOAT(11)
Sequelize.FLOAT(11, 12)               // FLOAT(11,12)

Sequelize.REAL                        // REAL        PostgreSQL only.
Sequelize.REAL(11)                    // REAL(11)    PostgreSQL only.
Sequelize.REAL(11, 12)                // REAL(11,12) PostgreSQL only.

Sequelize.DOUBLE                      // DOUBLE
Sequelize.DOUBLE(11)                  // DOUBLE(11)
Sequelize.DOUBLE(11, 12)              // DOUBLE(11,12)

Sequelize.DECIMAL                     // DECIMAL
Sequelize.DECIMAL(10, 2)              // DECIMAL(10,2)

Sequelize.DATE                        // DATETIME for mysql / sqlite, TIMESTAMP WITH TIME ZONE for postgres
Sequelize.DATE(6)                     // DATETIME(6) for mysql 5.6.4+. Fractional seconds support with up to 6 digits of precision
Sequelize.DATEONLY                    // DATE without time.
Sequelize.BOOLEAN                     // TINYINT(1)

Sequelize.ENUM('value 1', 'value 2')  // An ENUM with allowed values 'value 1' and 'value 2'
Sequelize.ARRAY(Sequelize.TEXT)       // Defines an array. PostgreSQL only.

Sequelize.JSON                        // JSON column. PostgreSQL only.
Sequelize.JSONB                       // JSONB column. PostgreSQL only.

Sequelize.BLOB                        // BLOB (bytea for PostgreSQL)
Sequelize.BLOB('tiny')                // TINYBLOB (bytea for PostgreSQL. Other options are medium and long)

Sequelize.UUID                        // UUID datatype for PostgreSQL and SQLite, CHAR(36) BINARY for MySQL (use defaultValue: Sequelize.UUIDV1 or Sequelize.UUIDV4 to make sequelize generate the ids automatically)

Sequelize.RANGE(Sequelize.INTEGER)    // Defines int4range range. PostgreSQL only.
Sequelize.RANGE(Sequelize.BIGINT)     // Defined int8range range. PostgreSQL only.
Sequelize.RANGE(Sequelize.DATE)       // Defines tstzrange range. PostgreSQL only.
Sequelize.RANGE(Sequelize.DATEONLY)   // Defines daterange range. PostgreSQL only.
Sequelize.RANGE(Sequelize.DECIMAL)    // Defines numrange range. PostgreSQL only.

Sequelize.ARRAY(Sequelize.RANGE(Sequelize.DATE)) // Defines array of tstzrange ranges. PostgreSQL only.

Sequelize.GEOMETRY                    // Spatial column.  PostgreSQL (with PostGIS) or MySQL only.
Sequelize.GEOMETRY('POINT')           // Spatial column with geomerty type.  PostgreSQL (with PostGIS) or MySQL only.
Sequelize.GEOMETRY('POINT', 4326)     // Spatial column with geomerty type and SRID.  PostgreSQL

範囲タイプ
//       '["2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00")'
// inclusive lower bound, exclusive upper bound
Timeline.create({ range: [new Date(Date.UTC(2016, 0, 1)), new Date(Date.UTC(2016, 1, 1))] });

// control inclusion
const range = [new Date(Date.UTC(2016, 0, 1)), new Date(Date.UTC(2016, 1, 1))];
range.inclusive = false; // '()'
range.inclusive = [false, true]; // '(]'
range.inclusive = true; // '[]'
range.inclusive = [true, false]; // '[)'

// or as a single expression
const range = [
  { value: new Date(Date.UTC(2016, 0, 1)), inclusive: false },
  { value: new Date(Date.UTC(2016, 1, 1)), inclusive: true },
];
// '("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00"]'

// composite form
const range = [
  { value: new Date(Date.UTC(2016, 0, 1)), inclusive: false },
  new Date(Date.UTC(2016, 1, 1)),
];
// '("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00")'

Timeline.create({ range });

特例
// empty range:
Timeline.create({ range: [] }); // range = 'empty'

// Unbounded range:
Timeline.create({ range: [null, null] }); // range = '[,)'
// range = '[,"2016-01-01 00:00:00+00:00")'
Timeline.create({ range: [null, new Date(Date.UTC(2016, 0, 1))] });

// Infinite range:
// range = '[-infinity,"2016-01-01 00:00:00+00:00")'
Timeline.create({ range: [-Infinity, new Date(Date.UTC(2016, 0, 1))] });

遅らせる
// Defer all foreign key constraint check to the end of a transaction
Sequelize.Deferrable.INITIALLY_DEFERRED

// Immediately check the foreign key constraints
Sequelize.Deferrable.INITIALLY_IMMEDIATE

// Don't defer the checks at all
Sequelize.Deferrable.NOT

Getters & setters
2つの方法で定義します.
  • は、属性の一部である
  • である.
    var Employee = sequelize.define('employee', {
      name:  {
        type     : Sequelize.STRING,
        allowNull: false,
        get      : function()  {
          var title = this.getDataValue('title');
          // 'this' allows you to access attributes of the instance
          return this.getDataValue('name') + ' (' + title + ')';
        },
      },
      title: {
        type     : Sequelize.STRING,
        allowNull: false,
        set      : function(val) {
          this.setDataValue('title', val.toUpperCase());
        }
      }
    });
    
    Employee
      .create({ name: 'John Doe', title: 'senior engineer' })
      .then(function(employee) {
        console.log(employee.get('name')); // John Doe (SENIOR ENGINEER)
        console.log(employee.get('title')); // SENIOR ENGINEER
      })
  • モデルオプションの一部として
  • var Foo = sequelize.define('foo', {
      firstname: Sequelize.STRING,
      lastname: Sequelize.STRING
    }, {
      getterMethods   : {
        fullName       : function()  { return this.firstname + ' ' + this.lastname }
      },
    
      setterMethods   : {
        fullName       : function(value) {
            var names = value.split(' ');
    
            this.setDataValue('firstname', names.slice(0, -1).join(' '));
            this.setDataValue('lastname', names.slice(-1).join(' '));
        },
      }
    });

    Validations検証
    var ValidateMe = sequelize.define('foo', {
      foo: {
        type: Sequelize.STRING,
        validate: {
          is: ["^[a-z]+$",'i'],     // will only allow letters
          is: /^[a-z]+$/i,          // same as the previous example using real RegExp
          not: ["[a-z]",'i'],       // will not allow letters
          isEmail: true,            // checks for email format ([email protected])
          isUrl: true,              // checks for url format (http://foo.com)
          isIP: true,               // checks for IPv4 (129.89.23.1) or IPv6 format
          isIPv4: true,             // checks for IPv4 (129.89.23.1)
          isIPv6: true,             // checks for IPv6 format
          isAlpha: true,            // will only allow letters
          isAlphanumeric: true,     // will only allow alphanumeric characters, so "_abc" will fail
          isNumeric: true,          // will only allow numbers
          isInt: true,              // checks for valid integers
          isFloat: true,            // checks for valid floating point numbers
          isDecimal: true,          // checks for any numbers
          isLowercase: true,        // checks for lowercase
          isUppercase: true,        // checks for uppercase
          notNull: true,            // won't allow null
          isNull: true,             // only allows null
          notEmpty: true,           // don't allow empty strings
          equals: 'specific value', // only allow a specific value
          contains: 'foo',          // force specific substrings
          notIn: [['foo', 'bar']],  // check the value is not one of these
          isIn: [['foo', 'bar']],   // check the value is one of these
          notContains: 'bar',       // don't allow specific substrings
          len: [2,10],              // only allow values with length between 2 and 10
          isUUID: 4,                // only allow uuids
          isDate: true,             // only allow date strings
          isAfter: "2011-11-05",    // only allow date strings after a specific date
          isBefore: "2011-11-05",   // only allow date strings before a specific date
          max: 23,                  // only allow values
          min: 23,                  // only allow values >= 23
          isArray: true,            // only allow arrays
          isCreditCard: true,       // check for valid credit card numbers
    
          // custom validations are also possible:
          isEven: function(value) {
            if(parseInt(value) % 2 != 0) {
              throw new Error('Only even values are allowed!')
            // we also are in the model's context here, so this.otherField
            // would get the value of otherField if it existed
            }
          }
        }
      }
    });

    エラーメッセージ
    isInt: {
      msg: "Must be an integer number of pennies"
    }

    または
    isIn: {
      args: [['en', 'zh']],
      msg: "Must be English or Chinese"
    }

    データ同期
    
    Project.sync()
    Task.sync()
    
    // Force the creation!
    Project.sync({force: true}) // this will drop the table first and re-create it afterwards
    
    // drop the tables:
    Project.drop()
    Task.drop()
    
    // event handling:
    Project.[sync|drop]().then(function() {
      // ok ... everything is nice!
    }).catch(function(error) {
      // oooh, did you enter wrong database credentials?
    })
    
    // Sync all models that aren't already in the database
    sequelize.sync()
    
    // Force sync all models
    sequelize.sync({force: true})
    
    // Drop all tables
    sequelize.drop()
    
    // emit handling:
    sequelize.[sync|drop]().then(function() {
      // woot woot
    }).catch(function(error) {
      // whooops
    })

    Models拡張
    var User = sequelize.define('user', { firstname: Sequelize.STRING });
    
    // Adding a class level method
    User.classLevelMethod = function() {
      return 'foo';
    };
    
    // Adding an instance level method
    User.prototype.instanceLevelMethod = function() {
      return 'bar';
    };

    索引
    sequelize.define('user', {}, {
      indexes: [
        // Create a unique index on email
        {
          unique: true,
          fields: ['email']
        },
    
        // Creates a gin index on data with the jsonb_path_ops operator
        {
          fields: ['data'],
          using: 'gin',
          operator: 'jsonb_path_ops'
        },
    
        // By default index name will be [table]_[fields]
        // Creates a multi column partial index
        {
          name: 'public_by_author',
          fields: ['author', 'status'],
          where: {
            status: 'public'
          }
        },
    
        // A BTREE index with a ordered field
        {
          name: 'title_index',
          method: 'BTREE',
          fields: ['author', {attribute: 'title', collate: 'en_US', order: 'DESC', length: 5}]
        }
      ]
    })