• Sequelize模型定义


    定义

    定义模型与表之间的映射,使用 define 方法.

    Sequelize 会自动增加 createdAtupdated 属性,这样能知道一个实例的创建时间和最终修改时间.如果不想自动生成,可以到configuration去看如何实现.

    var Project = sequelize.define('project', {
      title: Sequelize.STRING,
      description: Sequelize.TEXT
    })
    
    var Task = sequelize.define('task', {
      title: Sequelize.STRING,
      description: Sequelize.TEXT,
      deadline: Sequelize.DATE
    })
    

    还可以为每一个列增加一些可选属性

    var Foo = sequelize.define('foo', {
     // 自动设置默认值为 true
     flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true},
    
     //  日期默认值 => 当前时间
     myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW },
    
     // 设置列的 allowNull为 false 将会为该列增加 非空 属性
     // 在查询数据库之前想检车一个值是否为 空 ,看 validation 节
     title: { type: Sequelize.STRING, allowNull: false},
     
     // 创建两个拥有相同属性的值会抛出一个错误
     // The unique property can be either a boolean, or a string.
     // If you provide the same string for multiple columns, they will form a
     // composite unique key.
     someUnique: {type: Sequelize.STRING, unique: true},
     uniqueOne: { type: Sequelize.STRING,  unique: 'compositeIndex'},
     uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'}
     
     // unique 属性同时也是创建一个 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 和 PG 可以使用
     // Comments can be specified for each field for MySQL and PG
     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,
         //被引用模型的  列名  (是列名,即 field 名)
         key: 'id',
         // 检查外码约束,只支持 PostgreSQL .
         deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
       }
     }
    })
    

    数据类型

    更详细的可以上 DataTypes 看一看

    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.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 (with PostGIS) or MySQL only.
    

    integer, bigint, float 和 double 同样支持 unsigned 和 zerofill 约束

    Sequelize.INTEGER.UNSIGNED              // INTEGER UNSIGNED
    Sequelize.INTEGER(11).UNSIGNED          // INTEGER(11) UNSIGNED
    Sequelize.INTEGER(11).ZEROFILL          // INTEGER(11) ZEROFILL
    Sequelize.INTEGER(11).ZEROFILL.UNSIGNED // INTEGER(11) UNSIGNED ZEROFILL
    Sequelize.INTEGER(11).UNSIGNED.ZEROFILL // INTEGER(11) UNSIGNED ZEROFILL
    

    对象标记的用法

    // for enums:
    sequelize.define('model', {
      states: {
        type:   Sequelize.ENUM,
        values: ['active', 'pending', 'deleted']
      }
    })
    

    Getters & Setters 方法

    在模型中定义'对象-属性'的 getter 和 setter 方法是可能的,可以被用来保护与数据库列相映射的属性,还可以定义一些属性
    Getters 和 Setters 能以下面两种方式定义

    • 作为单个属性定义的一部分
    • 作为模型可选的一部分

    N.B: If a getter or setter is defined in both places then the function found in the relevant property definition will always take precedence.

    定义为属性的一部分

    var Employee = sequelize.define('employee', {
      name:  {
        type     : Sequelize.STRING,
        allowNull: false,
        get      : function()  {
          var title = this.getDataValue('title');
          // 'this' 允许你去获得实例的属性
          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
      })
    

    定义为模型的一部分

    下面是一个在模型内定义 getter 和 setter 方法的例子. 在这个例子里,fullname 的 getter 方法是在模型内定义假属性的一个例子
    ,因为 fullname 属性不存在于数据库模式中. 实际上,假属性可以通过以下两种方式来定义

    • 通过模型的 getter 方法
    • 或者通过使用带有 VIRTUAL 数据类型的列, VIRTUAL 数据类型可以有 validation , 然而 virtual 数据类型的 getter 方法不行

    注意在 fullName 的 getter 方法中引用的 this.firstNamethis.lastName 会触发各自的 getter 方法

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

    在 getter 和 setter 方法中使用的 Helper 方法

    • 获取一个基础属性值 , 经常用 this.getDataValue()
    • 设置一个基础属性值 , 经常用 this.setDataValue()
    • 坚持使用 getter 和 setter 方法 可以保护内部数据
    /* 'title' 属性的 getter 方法*/
    function(){
        return this.getDataValue('title');
    }
    
    /* 'title' 属性的 setter 方法*/
    function(){
        return this.setDataValue('title',title.toString().toLowerCase());
    }
    

    认证 (Validation)

    模型认证, 可以规定模型中每个属性的格式/内容 的认证. 其实现在

    当进行 create,updatesave操作时,认证会自动运行.也可以在实例中手动认证

    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 (foo@bar.com)
          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
            }
          }
        }
      }
    });
    

    注意当多个参数需要被传递到内嵌的认证函数时,多个参数应该被放在一个数组中.

    isIn: [['en', 'zh']],   // check the value is one of these
    

    不用 validator.js 提供的错误信息,自己定制错误信息

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

    可以看validator.js PROJECT获取更多细节


    认证器和 allowNull

    如果模型的列被设置为 allowNull:true 和 值被设置为 null的话,那认证器不会运行.

    举个栗子, 一个字符串的列长度设置为 最短为5, 但它可以存储 null

    模型认证

    var Pub = Sequelize.define('pub', {
      name: { type: Sequelize.STRING },
      address: { type: Sequelize.STRING },
      latitude: {
        type: Sequelize.INTEGER,
        allowNull: true,
        defaultValue: null,
        validate: { min: -90, max: 90 }
      },
      longitude: {
        type: Sequelize.INTEGER,
        allowNull: true,
        defaultValue: null,
        validate: { min: -180, max: 180 }
      },
    }, {
    
    
      //在这里对模型进行验证,只有 latitude 和 longtitude 同时被给予或都为空时成立
      validate: {
        bothCoordsOrNone: function() {
          if ((this.latitude === null) !== (this.longitude === null)) {
            throw new Error('Require either both latitude and longitude or neither')
          }
        }
      }
    })
    

    配置

    var Bar = sequelize.define('bar', { /* bla */ }, {
    
      // 不增加 TIMESTAMP 属性  (updatedAt, createdAt)
      timestamps: false,
      
      //不删除数据库中原有项, 增加新属性 deletedAt 并设置为 当前日期,
      //只有 TIMESTAMP 属性是允许的时候有效
      paranoid: true,
      
      // 不要使用驼峰式语法,用下划线代替
      // so updatedAt will be updated_at
      underscored: true,
      
      // 不允许调整表名 ; 
      // 默认地, sequelize 会自动转换所有传递的模型名字(define 的第一个参数)
      // 为复数
      // 如果不想这样,设置为 true
      freezeTableName: true,
    
      // 定义表名
      tableName: 'my_very_custom_table_name'
    })
    

    修改引擎

    var Person = sequelize.define('person', { /* attributes */ }, {
      engine: 'MYISAM'
    })
    
    // or globally
    var sequelize = new Sequelize(db, user, pw, {
      define: { engine: 'MYISAM' }
    })
    

    做注释

    var Person = sequelize.define('person', { /* attributes */ }, {
      comment: "I'm a table comment!"
    })
    

    导入

    可以把对表的定义放在单一文件中,返回对象恰好跟在 import 方法中定义的一样

    
      // in your server file - e.g. app.js
    var Project = sequelize.import(__dirname + "/path/to/models/project")
    
      // 定义在 project.js 文件中已经定义完成了
      // DataTypes  与上面解释的部分很像
    module.exports = function(sequelize, DataTypes) {
      return sequelize.define("project", {
        name: DataTypes.STRING,
        description: DataTypes.TEXT
      })
    }
    
    sequelize.import('project', function(sequelize, DataTypes) {
      return sequelize.define("project", {
        name: DataTypes.STRING,
        description: DataTypes.TEXT
      })
    })
    

    数据库同步

    开始一个新项目的时候,我们没有数据库架构,于是我们不需要 Sequelize.

    只需要说明我们的模型结构, 让库做剩下的部分,现在只支持 表的创建与删除

    // 只同步还没在数据库中的模型
    // Sync all models that aren't already in the database
    sequelize.sync()
    
    // 强制同步所有数据库的模型
    sequelize.sync({force: true})
    
    // 删除所有表
    sequelize.drop()
    
    // 开始执行
    sequelize.[sync|drop]().then(function() {
      // woot woot
    }).catch(function(error) {
      // whooops
    })
    

    因为.sync({force: true}) 是毁灭性的操作, 可以使用 match 选项去增加更多的安全检查(正则)

    // 删除以 '_test' 结尾的词
    sequelize.sync({ force: true, match: /_test$/ });
    

    模型的扩展

    Sequelize 允许我们去给 模型和相应的实例 传递定制方法

    var sequelize = new Sequelize('database', 'username', 'password', {
      // 其他可选的初始化可以放在这里
      define: {
        classMethods: {
          method1: function() {},
          method2: function() {}
        },
        instanceMethods: {
          method3: function() {}
        }
      }
    })
    
    // Example:
    var Foo = sequelize.define('foo', { /* attributes */});
    Foo.method1()
    Foo.method2()
    Foo.build().method3()
    

    索引

    Sequelize 支持在模型定义中增加索引, 这些索引在 Model.sync()sequelize.sync()时被创建.

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


    作者:kayorl
    链接:https://www.jianshu.com/p/a644e05503b0
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    镜像---移除
    镜像--保存于载入
    镜像、docker、容器三者关系
    容器管理
    HBase数据读写流程(1.3.1)
    HBase表的memstore与集群memstore
    HBase预分区方法
    HBase中的TTL与MinVersion的关系
    关于HBase的memstoreFlushSize。
    hbase java api样例(版本1.3.1,新API)
  • 原文地址:https://www.cnblogs.com/zzsdream/p/11065626.html
Copyright © 2020-2023  润新知