Sequelize 中文API文檔-2. Model 的定義、使用與Model類的API

Model相當於數據庫中表,有時它也會被稱爲“模型”或“工廠”。Model不能通過構造函數創建,而只能通過sequlize.define方法來定義或通過sequlize.import導入。通過define定義一個Model,就相當於定義了一種模型與數據表之間的映射關係,通過模型可以實現對錶記錄的增、刪、改、查等操作。

  1. 定義描述
  2. 模型的使用
  3. Model類的API

1. 定義描述

1.1 Definition - 模型定義

定義模型model和表之間的映射關係使用define方法。定義時Sequelize會自動爲其添加createdAtupdatedAt兩個屬性(屬性相當於表中的字段),這樣你就可以知道數據什麼時候插入了數據庫和什麼時候進行了更新。

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 後,會爲列添加  NOT NULL 非空限制
 // 這意味着當執行查詢(插入/更新)時相關字段爲空會從數據庫層拋出錯誤
 // 如果想在執行查詢時進行值檢測,請參考“驗證”一節
 title: { type: Sequelize.STRING, allowNull: false},

 // 添加唯一(unique)約束後插入重複值會報錯
 // unique屬性可以是boolean 或 string類型
 // 如果爲多個字段添加了相同的字符串那麼將會是一個符合唯一鍵
 someUnique: {type: Sequelize.STRING, unique: true},
 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},

 // autoIncrement 選項用於創建一個自增的整型列
 incrementMe: { type: Sequelize.INTEGER, autoIncrement: true },

 // Comments 可以在MySQL 和 PG中指定定段描述
 hasComment: { type: Sequelize.INTEGER, comment: "I'm a comment!" },

 // 可以通過 "field" 屬性來指定數據庫中的字段名
 fieldWithUnderscores: { type: Sequelize.STRING, field: "field_with_underscores" },

 // 通過references選項可以創建外鍵:
 bar_id: {
   type: Sequelize.INTEGER,

   references: {
     // 引用另一個模型
     model: Bar,

     // 連接模型的列表
     key: 'id',

     // 強制使用外鍵約束,僅適用於 PostgreSQL
     deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
   }
 }
})

如果你不想在模型中使用時間戳,而只需要一些時間;或者你正在使用一個已經存在的數據庫,而其中的列名與你的所需要並不一致。更多配置請參考模型配置


1.2 Data types - 數據類型

在定義模型時,我們會指定其屬性(字段)的數據類型,下面是Sequelize中支持數據類型及其與數據庫中字段類型的對應關係:

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                        //   PostgreSQL 和 SQLite 中爲 UUID, MySQL 中爲CHAR(36) BINARY (使用 defaultValue: Sequelize.UUIDV1 或 Sequelize.UUIDV4 生成默認值)

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

BLOB類型中你可以插入字符串或二進制buffer,在進行查詢時其總是會返回buffer

如果要使用PostgreSQL的TIMESTAMP WITHOUT TIME ZONE類型,那麼你需要存入一個不同的時區,並使用pg庫進行轉換

require('pg').types.setTypeParser(1114, function(stringValue) {
  return new Date(stringValue + "+0000");
  // e.g., UTC offset. Use any offset that you would like.
});

下面是一個額外支持的類型,如:integer, bigint, float 和 double 也同樣支持 unsigned 和 zerofill。但這些屬性並不能在PostgreSQL中使用:

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.define('model', {
  states: {
    type:   Sequelize.ENUM,
    values: ['active', 'pending', 'deleted']
  }
})


1.3 Deferrable - 延時執行

當你指定一個可選的外鍵列,那麼可以在PostgreSQL定義爲Deferrable類型。以下選項可用:

// 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


1.4 Getters & setters - 訪問器&設置器

可以在你的模型中將對象屬性定義爲訪問/設置函數

訪問器&設置器有以下兩種定義方式:

  • 做爲一個屬性定義
  • 做爲模型選項

做爲一個屬性定義

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

做爲模型選項

在下面的示例中,定義了一個名爲fullName的訪問器,它是對this.firstnamethis.lastname兩個屬性引用,這個屬性的一個假屬性它並不是數據庫中的一部分。定義假屬性可以使用訪問器或定義爲VIRTUAL類型兩種方式,Virtual類型可以驗證而訪問器則不能。

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

訪問器&設置器內部定義的幫助函數:

檢索底層屬性值-總是使用this.getDataValue()

/* 訪問 'title' 的屬性 */
function() {
    return this.getDataValue('title');
}

設置底層屬性值-總是使用this.setDataValue()

/* 設置 'title' 的屬性 */
function() {
    return this.setDataValue('title', title.toString().toLowerCase());
}


1.5 Validations - 驗證

模型驗證,讓我們可以模型的每個屬性執行驗證。

我們通過模型列屬性的validate屬性來添加驗證,這些驗證會在模型實例執行createupdatesave自動執行。也可以通過instance.validate()方法,來手工驗證模型實例。

var ValidateMe = sequelize.define('foo', {
  foo: {
    type: Sequelize.STRING,
    validate: {
      is: ["^[a-z]+$",'i'],     // 只允許字母
      is: /^[a-z]+$/i,          // 只允許字母
      not: ["[a-z]",'i'],       // 不能使用字母
      isEmail: true,            // 檢測郵箱格式 ([email protected])
      isUrl: true,              // 檢查Url格式 (http://foo.com)
      isIP: true,               // 檢查 IPv4 或 IPv6 格式
      isIPv4: true,             // 檢查 IPv4
      isIPv6: true,             // 檢查 IPv6
      isAlpha: true,            // 不能使用字母
      isAlphanumeric: true,     // 只允許字母數字字符
      isNumeric: true,          // 只能使用數字
      isInt: true,              // 只能是整數
      isFloat: true,            // 只能是浮點數
      isDecimal: true,          // 檢查數字
      isLowercase: true,        // 檢查小寫字母
      isUppercase: true,        // 檢查大寫字母
      notNull: true,            // 不允許null
      isNull: true,             // 只能爲null
      notEmpty: true,           // 不能空字符串
      equals: 'specific value', // 只能使用指定值
      contains: 'foo',          // 必須包含子字符串
      notIn: [['foo', 'bar']],  // 不能是數組中的任意一個值
      isIn: [['foo', 'bar']],   // 只能是數組中的任意一個值
      notContains: 'bar',       // 不能包含子字符串
      len: [2, 10],              // 值的長度必在 2 和 10 之間
      isUUID: 4,                // 只能是UUID
      isDate: true,             // 只能是日期字符串
      isAfter: "2011-11-05",    // 只能使用指定日期之後的時間
      isBefore: "2011-11-05",   // 只能使用指定日期之前的時間
      max: 23,                  // 允許的最大值
      min: 23,                  // 允許的最小值
      isArray: true,            // 不能使用數組
      isCreditCard: true,       // 檢查是有效的信用卡

      // 也可以自定義驗證:
      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
        }
      }
    }
  }
});

驗證時可以使用自定義的錯誤信息代替validator.js的默認信息,只需要在通過對象或數組的方式提供參數即可:

isInt: {
  msg: "Must be an integer number of pennies"
}

或者參數中同樣需要提供args屬性:

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

模型驗證

Validations同可以用於模型的檢測,只需要在字段定義之後定義驗證即可。如,在經緯度的應用的我們會需要latitudelongitude都不爲空或都爲空,這時我們可以像下面這樣驗證:

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 }
  },
}, {
  validate: {
    bothCoordsOrNone: function() {
      if ((this.latitude === null) !== (this.longitude === null)) {
        throw new Error('Require either both latitude and longitude or neither')
      }
    }
  }
})


1.6 Configuration - 配置

定義模型時,可以通過配置來設置列名等相關信息:

var Bar = sequelize.define('bar', { /* bla */ }, {
  // 不要添加時間戳屬性 (updatedAt, createdAt)
  timestamps: false,

  // 不從數據庫中刪除數據,而只是增加一個 deletedAt 標識當前時間
  // paranoid 屬性只在啓用 timestamps 時適用
  paranoid: true,

  // 不使用駝峯式命令規則,這樣會在使用下劃線分隔
  // 這樣 updatedAt 的字段名會是 updated_at
  underscored: true,

  // 禁止修改表名. 默認情況下
  // sequelize會自動使用傳入的模型名(define的第一個參數)做爲表名
  // 如果你不想使用這種方式你需要進行以下設置
  freezeTableName: true,

  // 定義表名
  tableName: 'my_very_custom_table_name'
})

如果你想sequelize處理時間戳,但只在個別情況下使用,那麼你可以對使用的列單獨重載:

var Foo = sequelize.define('foo',  { /* bla */ }, {
  // 不要忘了啓用 timestamps
  timestamps: true,

  // 不想使用 createdAt
  createdAt: false,

  // 想 updatedAt 的實際名爲 'updateTimestamp'
  updatedAt: 'updateTimestamp'

  // 要將 deletedAt 設置爲 destroyTime (注意要啓用paranoid)
  deletedAt: 'destroyTime',
  paranoid: true
})

配置時,也可以修改數據庫引擎。如,將默認的InnoDB修改爲MyISAM:

var Person = sequelize.define('person', { /* attributes */ }, {
  engine: 'MYISAM'
})

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

或者指定一個表描述(MySql和PG中):

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

注意:字段attributes同樣可以添加comment屬性,但出於兼容性考慮自sequelize V1.7+起已不再將此屬性同步到數據庫中,但爲字段添加這個屬性依然是增加可讀性的不錯的方式。


1.7 Import - 模型導入

我們可以將模型定義爲一個單獨的文件,並通過 導入。通過文件導入返回的對象與通過defined方法定義的模型完全一致,兩者都是instance模型實例。自v1.5.0起,sequlize會對導入進行緩存,這樣就不用擔心多次對文件修改造成的一些問題。

如,我們在project.js文件中定義一個名爲project的模型:

// 這個文件定義於 /path/to/models/project.js
module.exports = function(sequelize, DataTypes) {
  return sequelize.define("project", {
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  })
}

我們可以app.js或其它需要的地方引入定義的模型:

var Project = sequelize.import(__dirname + "/path/to/models/project")

import同樣可以使用回調函數參數的使用方式:

sequelize.import('project', function(sequelize, DataTypes) {
  return sequelize.define("project", {
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  })
})


1.8 Database synchronization - 數據庫同步

開始一個新項目時,我們並沒有數據庫結構,使用Sequelize時,並不需要先定義好數據庫結構。我們只要定義好模型,然後進行同步即可。

Sequelize支持創建表和刪除表:

// 通過 sync 方法同步數據結構
// 即,創建表
Project.sync()
Task.sync()

// 強制創建
// 通過設置 force 屬性會首先刪除表並重新創建
Project.sync({force: true})

// 刪除表
Project.drop()
Task.drop()

// 事件處理
Project.[sync|drop]().then(function() {
  // 處理成功
}).catch(function(error) {
  // 出了點問題^~^
})

.sync({ force: true })會刪除並重建表,這時我們可以添加match選項,只重建正則表達式匹配的表:

sequelize.sync({ force: true, match: /_test$/ });


1.9 Expansion of models - 模型擴展

開始一個新項目時,我們並沒有數據庫結構,使用Sequelize時,並不需要先定義好數據庫結構。我們只要定義好模型,然後進行同步即可。


自定義方法

Sequelize允許我們爲實例添加自定義方法,可以像下面這樣定義:

var Foo = sequelize.define('foo', { /* attributes */}, {
  classMethods: {
    method1: function(){ return 'smth' }
  },
  instanceMethods: {
    method2: function() { return 'foo' }
  }
})

// Example:
Foo.method1()
Foo.build().method2()

虛擬訪問器

也可以設置虛擬訪問器:

var User = sequelize.define('user', { firstname: Sequelize.STRING, lastname: Sequelize.STRING }, {
  instanceMethods: {
    getFullname: function() {
      return [this.firstname, this.lastname].join(' ')
    }
  }
})

// Example:
User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar'

全局方法

還可以定義用於所有模型實例的全局方法:

var sequelize = new Sequelize('database', 'username', 'password', {
  // Other options during the initialization could be here
  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}]
    }
  ]
})


2. 模型的使用

2.1 Data retrieval / Finders - 數據索引/查找

查找方法是爲了從數據庫中查詢數據,這些方法不是返回原始數據對象,而是返回模型實例。因會其返回的是模型實例,所以在文檔的查詢結果中可以任意調用模型實例的成員、方法等。(更多實例介紹請參考:instance

下面是一些常用的查詢方法。

find - 從數據庫中查找一個指定元素

// 按已知 id查找
Project.findById(123).then(function(project) {
  // project 是一個 Project 實例,且包含存儲在數據中的數據
  // 當不存在 id 爲123的記錄時 project 爲 null
})

// 按屬性查找
Project.findOne({ where: {title: 'aProject'} }).then(function(project) {
  // project 是匹配到的第一個 title 爲 'aProject' 的 Projects 或 null
})


Project.findOne({
  where: {title: 'aProject'},
  attributes: ['id', ['name', 'title']]
}).then(function(project) {
  // project 是匹配到的第一個 title 爲 'aProject' 的 Projects 或 null
  // project 的 project.title 屬性中會包含 'name'
})

findOrCreate - 從數據庫中查找一個指定元素如果不存在則創建記錄

findOrCreate可用於檢測一個不確定是否存在的元素,如果存在則返回記錄,不存在時會使用提供的默認值新建記錄。

如,當數據不存在時,其執行效果如下:

User
  .findOrCreate({where: {username: 'itbilu.com'}, defaults: {job: 'Technical Lead JavaScript'}})
  .spread(function(user, created) {
    console.log(user.get({
      plain: true
    }))
    console.log(created)

    /*
      {
        username: 'itbilu.com',
        job: 'Technical Lead JavaScript',
        id: 1,
        createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET),
        updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET)
      }
      created: true
    */
  })

當數據存在時,會返回記錄:

User
  .create({ username: 'fnord', job: 'omnomnom' })
  .then(function() {
    User
      .findOrCreate({where: {username: 'fnord'}, defaults: {job: 'something else'}})
      .spread(function(user, created) {
        console.log(user.get({
          plain: true
        }))
        console.log(created)

        /*
          {
            username: 'fnord',
            job: 'omnomnom',
            id: 2,
            createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET),
            updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET)
          }
          created: false
        */
      })
  })

findAndCountAll - 從數據庫中查找多個元素,返回數據與記錄總數

這個方法是findAllcount兩個方法的便捷形式,這在你想使用limitoffset進行分頁查詢時非常有用。

在返回值中,會包含以下兩個屬性:

  • count - 整數,匹配到的總記錄數
  • rows - 對象數據,通過 limit 和 offset匹配的當前頁數據
Project
  .findAndCountAll({
     where: {
        title: {
          $like: 'foo%'
        }
     },
     offset: 10,
     limit: 2
  })
  .then(function(result) {
    console.log(result.count);
    console.log(result.rows);
  });

findAndCountAll同樣支持使用include包含,使用包含時只有將required設置爲true纔會添加到count部分:

User.findAndCountAll({
  include: [
     { model: Profile, required: true}
  ],
  limit: 3
});

使用include時,兩個模型之間應該存在主/外鍵關係,如果不存在就應該在include中手工建立連接。

在上面的示例中,爲Profile設置了required,所以在查詢時會使用INNER JOIN內連接。

findAll - 從數據庫中查找多個元素

findAndCountAll中使用的查詢選項同樣適用於findAll方法。

// 查詢多條記錄
Project.findAll().then(function(projects) {
  // projects 是一個包含Project實例的數組
})

// 同樣的,all是findAll的別名方法:
Project.all().then(function(projects) {
  // projects 是一個包含Project實例的數組
})

// 通過指定屬性查找
Project.findAll({ where: { name: 'A Project' } }).then(function(projects) {
// projects 是一個包含 Project 實例的數組
})

// 查詢時使用字符串替換
Project.findAll({ where: ["id > ?", 25] }).then(function(projects) {
  // projects 是一個包含 Project 實例的數組,各實例的id 大於25
})

// 查詢指定範圍
Project.findAll({ where: { id: [1,2,3] } }).then(function(projects) {
  // projects 是一個包含 Project 實例的數組,各實例id 是1, 2, 或 3
  // 這在實例執行時,會使用 IN查詢
})

Project.findAll({
  where: {
    id: {
      $and: {a: 5}           // AND (a = 5)
      $or: [{a: 5}, {a: 6}]  // (a = 5 OR a = 6)
      $gt: 6,                // id > 6
      $gte: 6,               // id >= 6
      $lt: 10,               // id < 10
      $lte: 10,              // id <= 10
      $ne: 20,               // id != 20
      $between: [6, 10],     // BETWEEN 6 AND 10
      $notBetween: [11, 15], // NOT BETWEEN 11 AND 15
      $in: [1, 2],           // IN [1, 2]
      $notIn: [1, 2],        // NOT IN [1, 2]
      $like: '%hat',         // LIKE '%hat'
      $notLike: '%hat'       // NOT LIKE '%hat'
      $iLike: '%hat'         // ILIKE '%hat' (case insensitive)  (PG only)
      $notILike: '%hat'      // NOT ILIKE '%hat'  (PG only)
      $overlap: [1, 2]       // && [1, 2] (PG array overlap operator)
      $contains: [1, 2]      // @> [1, 2] (PG array contains operator)
      $contained: [1, 2]     // <@ [1, 2] (PG array contained by operator)
      $any: [2,3]            // ANY ARRAY[2, 3]::INTEGER (PG only)
    },
    status: {
      $not: false,           // status NOT FALSE
    }
  }
})

IN/OR 等複合篩選

如果要在查詢中使用ANDORDOT等篩選條件,可以查詢的where中指定$and$or$not等屬性:

Project.findOne({
  where: {
    name: 'a project',
    $or: [
      { id: [1,2,3] },
      { id: { $gt: 10 } }
    ]
  }
})

Project.findOne({
  where: {
    name: 'a project',
    id: {
      $or: [
        [1,2,3],
        { $gt: 10 }
      ]
    }
  }
})

這個查詢生成的實際SQL語句爲:

SELECT *
FROM `Projects`
WHERE (
  `Projects`.`name` = 'a project'
   AND (`Projects`.`id` IN (1,2,3) OR `Projects`.`id` > 10)
)
LIMIT 1;

$not示例:

Project.findOne({
  where: {
    name: 'a project',
    $not: [
      { id: [1,2,3] },
      { array: { $contains: [3,4,5] } }
    ]
  }
});

將生成以下語句:

SELECT *
FROM `Projects`
WHERE (
  `Projects`.`name` = 'a project'
   AND NOT (`Projects`.`id` IN (1,2,3) OR `Projects`.`array` @> ARRAY[1,2,3]::INTEGER[])
)
LIMIT 1;

對數據集使用limitoffsetorder 和 group

// 使用 limit 限制返回結果數
Project.findAll({ limit: 10 })

// 跳過前 10 條結果
Project.findAll({ offset: 10 })

// 跳過前 10 條結果後,返回兩條數據
Project.findAll({ offset: 10, limit: 2 })

分組與排序的語法是相似的,如下:

Project.findAll({order: 'title DESC'})
// ORDER BY title DESC

Project.findAll({group: 'name'})
// GROUP BY name

傳入簡單的字符串時,查詢字符串會逐字查詢,即列名不轉義。如果需要列名轉義,可以提供一個數組參數。

something.findOne({
  order: [
    'name',
    // will return `name`
    'username DESC',
    // will return `username DESC` -- i.e. don't do it!
    ['username', 'DESC'],
    // will return `username` DESC
    sequelize.fn('max', sequelize.col('age')),
    // will return max(`age`)
    [sequelize.fn('max', sequelize.col('age')), 'DESC'],
    // will return max(`age`) DESC
    [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
    // will return otherfunction(`col1`, 12, 'lalala') DESC
    [sequelize.fn('otherfunction', sequelize.fn('awesomefunction', sequelize.col('col'))), 'DESC']
    // will return otherfunction(awesomefunction(`col`)) DESC, This nesting is potentially infinite!
    [{ raw: 'otherfunction(awesomefunction(`col`))' }, 'DESC']
    // This won't be quoted, but direction will be added
  ]
})

更多關於聚合查詢,請參考:在Sequelize中使用group by分組聚合查詢

原始查詢

默情況下,Sequlize人爲查詢結構創建實例,通過這個實例可以進行數據的更新、刪除等操作。有時候我只需要顯示數據集,而不需要進行處理,這時可以通過設置raw選項來返回原始數據:

// 增加 raw 選項後,會返回數據庫中的原始結果
Project.findAll({ where: { ... }, raw: true })

count - 統計數據庫中的元素數

count可以統計數據庫中的元素數:

Project.count().then(function(c) {
  console.log("There are " + c + " projects!")
})

Project.count({ where: ["id > ?", 25] }).then(function(c) {
  console.log("There are " + c + " projects with an id greater than 25.")
})

max - 查找指定表中最大值

// 數據庫中有3條記錄,年齡分別是 10, 5, 40
Project.max('age').then(function(max) {
  // 會返回 40
})

Project.max('age', { where: { age: { lt: 20 } } }).then(function(max) {
  // 會返回 10
})

min - 查找指定表中最小值

// 數據庫中有3條記錄,年齡分別是 10, 5, 40
Project.min('age').then(function(min) {
  // 會返回 5
})

Project.min('age', { where: { age: { $gt: 5 } } }).then(function(min) {
  // 會返回 10
})

sum - 對指定屬性求和

// 數據庫中有3條記錄,年齡分別是 10, 5, 40
Project.sum('age').then(function(sum) {
  // 會返回 55
})

Project.sum('age', { where: { age: { $gt: 5 } } }).then(function(sum) {
  // 會返回 50
})


2.2 Eager loading - 預加載

從數據庫中加載數據時,除數據本身外還想得到與之相關聯的數據-這就是所謂的預加載。也就是說,使用findfindAll查詢數據時,通過include屬性同時加載關聯的數據。

假設有以下數據結構:

var User = sequelize.define('user', { name: Sequelize.STRING })
  , Task = sequelize.define('task', { name: Sequelize.STRING })
  , Tool = sequelize.define('tool', { name: Sequelize.STRING })

Task.belongsTo(User)
User.hasMany(Task)
User.hasMany(Tool, { as: 'Instruments' })

sequelize.sync().then(function() {
  // this is where we continue ...
})

通過belongsTohasMany建立關係後,就可以像下面這樣查詢:

Task.findAll({ include: [ User ] }).then(function(tasks) {
  console.log(JSON.stringify(tasks))

  /*
    [{
      "name": "A Task",
      "id": 1,
      "createdAt": "2013-03-20T20:31:40.000Z",
      "updatedAt": "2013-03-20T20:31:40.000Z",
      "userId": 1,
      "user": {
        "name": "John Doe",
        "id": 1,
        "createdAt": "2013-03-20T20:31:45.000Z",
        "updatedAt": "2013-03-20T20:31:45.000Z"
      }
    }]
  */
})

由於TaskUser1對多的關係,所在以查詢時user會做爲一個對象屬性被同時加載。

下面我們進行一個多對多的查詢:

User.findAll({ include: [ Task ] }).then(function(users) {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "tasks": [{
        "name": "A Task",
        "id": 1,
        "createdAt": "2013-03-20T20:31:40.000Z",
        "updatedAt": "2013-03-20T20:31:40.000Z",
        "userId": 1
      }]
    }]
  */
})

多對多的關係中,相關數據會做爲一個數組屬性被同時加載。

關聯查詢時,可以使用as選項爲關係數據指定別名:

User.findAll({ include: [{ model: Tool, as: 'Instruments' }] }).then(function(users) {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "Instruments": [{
        "name": "Toothpick",
        "id": 1,
        "createdAt": null,
        "updatedAt": null,
        "userId": 1
      }]
    }]
  */
})

關聯查詢時,同樣可以使用where選項對關聯數據進行篩選:

User.findAll({
    include: [{
        model: Tool,
        as: 'Instruments',
        where: { name: { $like: '%ooth%' } }
    }]
}).then(function(users) {
    console.log(JSON.stringify(users))

    /*
      [{
        "name": "John Doe",
        "id": 1,
        "createdAt": "2013-03-20T20:31:45.000Z",
        "updatedAt": "2013-03-20T20:31:45.000Z",
        "Instruments": [{
          "name": "Toothpick",
          "id": 1,
          "createdAt": null,
          "updatedAt": null,
          "userId": 1
        }]
      }],

      [{
        "name": "John Smith",
        "id": 2,
        "createdAt": "2013-03-20T20:31:45.000Z",
        "updatedAt": "2013-03-20T20:31:45.000Z",
        "Instruments": [{
          "name": "Toothpick",
          "id": 1,
          "createdAt": null,
          "updatedAt": null,
          "userId": 1
        }]
      }],
    */
  })

注意:使用include.where條件時,include.requied會被隱式的設置爲true,即在查詢時會使用INNER JOIN內連接。

全關聯

如果多個模型間存在關聯關係,而我們在查詢時又要查詢所有的數據,就可以設置all: true來關聯所有模型:

User.findAll({ include: [{ all: true }]});

包括軟刪除的數據

如果要在結果中包含軟刪除的數據,請將include.paranoid設置爲true

User.findAll({
    include: [{
        model: Tool,
        where: { name: { $like: '%ooth%' } },
        paranoid: true // 查詢並加載軟刪除的數據
    }]
});

預加載關聯數據的排序

1對多(one-to-many)的關係中:

Company.findAll({ include: [ Division ], order: [ [ Division, 'name' ] ] });
Company.findAll({ include: [ Division ], order: [ [ Division, 'name', 'DESC' ] ] });
Company.findAll({
  include: [ { model: Division, as: 'Div' } ],
  order: [ [ { model: Division, as: 'Div' }, 'name' ] ]
});
Company.findAll({
  include: [ { model: Division, as: 'Div' } ],
  order: [ [ { model: Division, as: 'Div' }, 'name', 'DESC' ] ]
});
Company.findAll({
  include: [ { model: Division, include: [ Department ] } ],
  order: [ [ Division, Department, 'name' ] ]
});

多對多(many-to-many)的關係中同樣可以使用排序:

Company.findAll({
  include: [ { model: Division, include: [ Department ] } ],
  order: [ [ Division, DepartmentDivision, 'name' ] ]
});

嵌套預加載

可以在關聯模型中嵌套預加載關係模型:

User.findAll({
  include: [
    {model: Tool, as: 'Instruments', include: [
      {model: Teacher, include: [ /* etc */]}
    ]}
  ]
}).then(function(users) {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "Instruments": [{ // 1:M and N:M association
        "name": "Toothpick",
        "id": 1,
        "createdAt": null,
        "updatedAt": null,
        "userId": 1,
        "Teacher": { // 1:1 association
          "name": "Jimi Hendrix"
        }
      }]
    }]
  */
})

這會生成一個外連接,但where子句的關係模型會使用內連接並返回唯一一個子句:

User.findAll({
  include: [{
    model: Tool,
    as: 'Instruments',
    include: [{
      model: Teacher,
      where: {
        school: "Woodstock Music School"
      },
      required: false
    }]
  }]
}).then(function(users) {
  /* ... */
})

include同樣支持嵌套加載:

User.findAll({ include: [{ all: true, nested: true }]});


3. Model類的API

Model相當於數據庫中表,有時你也會看到它被稱爲“模型”、或簡單的被爲“工廠”。這個類不能顯式的(通過構造函數)創建實例,而是應該通過sequelize.define方法來創建,對於已經創建可以通過sequelize.import方法來導入。

3.1 removeAttribute() - 移除屬性

removeAttribute([attribute])

從已定義的模型中移除屬性

參數

名稱類型說明
[attribute]String 

使用示例:

let User = sequelize.define('user', {
  firstName: Sequelize.STRING,
  lastName: Sequelize.STRING
});

User.sync().then(function(result){
  User.create({firstName:'xxxx', lastName:'xxxx'})
  .then(function(result){
    User.findOne({raw:true})
    .then(function(result){
      console.log(result); // { id: 1, firstName: 'xxxx', lastName: 'xxxx'}

      // 移'firstName'屬性
      User.removeAttribute('firstName');
      User.findOne({raw:true})
      .then(function(result){
        console.log(result);  // // { id: 1, lastName: 'xxxx'}
      })
    })  
  })
})


3.2 sync() - 同步模型到數據庫

sync() -> Promise.

同步Model結構到數據庫中,即:在數據庫中創建表。執行成功後,會在回調中返回模弄的實例(this)。

sequelize.sync的不同

Model.sync()只會同步當前模型到數據庫中,而sequelize.sync()會同步sequelize實例中定義所有模型。

let User = sequelize.define('user', {
  firstName: Sequelize.STRING,
  lastName: Sequelize.STRING
});

let Role = sequelize.define('role', {
  roleName: Sequelize.STRING
});

let UserRole = sequelize.define('userRole', {
  userId: Sequelize.INTEGER,
  roleId: Sequelize.STRING
});

User.sync().then(function(result){
    // 同步了'User'一個模型
})

sequelize.sync().then(function(result){
  // 同步了'Role'、'UserRole'、'UserRole'三個模型
})

相關


3.3 drop() - 刪除數據庫中的表

drop([options]) -> Promise

刪除Model在數據庫中對應的表。

參數

名稱類型屬性
[options]Object 
[options.cascade=false]Boolean同時移除依賴於該表的對象,如視圖。僅 postgres適用
[options.logging=false]Function一個函數用於打印查詢時的sql
[options.benchmark=false]Boolean在打印日誌時同時輸出執行SQL花費的時候(毫秒)


3.4 schema() - 指定schema

schema(schema, [options]) -> this

Model指定schema(數據庫)。在postgres中將會設置爲"schema"."tableName",而在mysql和sqlite中將會設置爲'schema.tablename'

參數

名稱類型屬性
schemaStringschema名
[options]Object 
[options.schemaDelimiter='.']Stringschema與表名的分隔符
[options.logging=false]Function一個函數用於打印查詢時的sql
[options.benchmark=false]Boolean在打印日誌時同時輸出執行SQL花費的時候(毫秒)


3.5 getTableName() - 獲取表名

getTableName([options]) -> String|Object

獲取Model在數據庫中的表名。在未指定schema時會返回模型名,或返回一個包含tableNameschemadelimiter屬性的對象。

參數

名稱類型屬性
schemaStringschema名
[options]Object 
[options.logging=false]Function一個函數用於打印查詢時的sql
[options.benchmark=false]Boolean在打印日誌時同時輸出執行SQL花費的時候(毫秒)


3.6 addScope() - 添加限制範圍

addScope(name, scope, [options])

爲模型添加一個新的限制範圍。在定義模型時如果未指定驗證,這一方法會非常有用。

如果指定的限制已經存在,默認會拋出異常,這時可以傳入override: true選項來解決。

參數

名稱類型說明
nameString限制範圍名。使用defaultScope是,會替換默認的限制
scopeObject | Function 
[options]Object 
[options.override=false]Boolean 


3.7 scope() - 應用限制範圍

scope(options*) -> Model

在應用在define定義模型時創建的作用範圍。如,在定義模型時我們會像下面這樣創建作用範圍:

var Model = sequelize.define('model', attributes, {
  defaultScope: {
    where: {
      username: 'dan'
    },
    limit: 12
  },
  scopes: {
    isALie: {
      where: {
        stuff: 'cake'
      }
    },
    complexFunction: function(email, accessLevel) {
      return {
        where: {
          email: {
            $like: email
          },
          accesss_level {
            $gte: accessLevel
          }
        }
      }
    }
  }
})

定義默認的限制範圍後,默認限制會在每次查詢時起作用:

Model.findAll() // WHERE username = 'dan'
Model.findAll({ where: { age: { gt: 12 } } }) // WHERE age > 12 AND username = 'dan'

我們可以通過scope()像下面這樣應用限制範圍:

Model.scope({ method: ['complexFunction' '[email protected]', 42]}).findAll()
// WHERE email like '[email protected]%' AND access_level >= 42


3.8 findAll() - 查詢多條數據

findAll([options]) -> Promise.<Array.<Instance>>

查詢多個實例(多條數據)。

如,在查詢中使用AND=

Model.findAll({
  where: {
    attr1: 42,
    attr2: 'cake'
  }
})
// WHERE attr1 = 42 AND attr2 = 'cake'

在查詢中使用大於小於等:

Model.findAll({
  where: {
    attr1: {
      $gt: 50
    },
    attr2: {
      $lte: 45
    },
    attr3: {
      $in: [1,2,3]
    },
    attr4: {
      $ne: 5
    }
  }
})
// WHERE attr1 > 50 AND attr2 <= 45 AND attr3 IN (1,2,3) AND attr4 != 5

在查詢中使用OR

Model.findAll({
  where: {
    name: 'a project',
    $or: [
      {id: [1, 2, 3]},
      {
        $and: [
          {id: {gt: 10}},
          {id: {lt: 100}}
        ]
      }
    ]
  }
});

//WHERE `Model`.`name` = 'a project' AND (`Model`.`id` IN (1, 2, 3) OR (`Model`.`id` > 10 AND `Model`.`id` < 100));

查詢成功後會返回包含多個實例(instance)的數組。

別名:all

相關

參數

名稱類型說明
[options]Object 
[options.where]Object一個描述查詢限制範圍(WHERE條件)的對象
[options.attributes]Array.<String> | Object要查詢的屬性(字段)列表,或一個include 和 exclude 對象的鍵。
要對屬性進行重命名,可以傳入一個包含兩個元素的數組-第一個表示屬性在數據庫中的名稱或(或一些類似Sequelize.literalSequelize.fn等的表達式),第二個屬性表示要在返回實例中使用的名稱
[options.attributes.include]Array.<String>選擇所有模型屬性並添加一些附加值,用於聚合計算。如:
{attributes:{ 
include:[[sequelize.fn('COUNT', sequelize.col('id')),'total']]}
[options.attributes.exclude]Array.<String>選擇模型中除少數屬性外的所有屬性,這主要出於安全目錄。 如:
{ attributes: { exclude: ['password'] } }
[options.paranoid=true]Booleantrue時,只會未刪除的記錄會返回,否則會返回刪除和未刪除的全部記錄
[options.include]Array.<Object | Model>一個用於左連接的連接列表,
支持{ include: [ Model1, Model2, ...]} 或 { include: [{ model: Model1, as: 'Alias' }]}的形式
如果你的連接要設置as (如 X.hasMany(Y, { as: 'Z }, 你需要將要加載的 Y 的as屬性指定爲Z)
[options.include[].model]Model你想要加載的模型
[options.include[].as]String別名關係,如果你想對要加載的模型起別名。
對於 hasOne / belongsTo, 這地應該使用單數形式名,而對於hasMany則應該使用複數形式名
[options.include[]
.association]
Association想要加載的關係(這可以用來替代提供的一個model/as對)
[options.include[].where]Object用於子模型的WHERE分句。注意,這會對要加載的使用內連接,除非顯示指定required: false
[options.include[].or=false]Boolean是否將 ON 和 WHERE 分名與 OR綁定在一起而不是替換 AND
[options.include[].on]Object爲連接提供你的 ON 條件
[options.include[].attributes]Array.<String>要從子模型中查詢的屬性列表
[options.include[].required]Boolean如果爲true,會轉換爲內連接。這意味着,只有匹配到子模型的父模型纔會被加載。include.where設置後爲True,其它情況 false
[options.include[].separate]Boolean如果爲true,運行一個單獨的查詢來獲取關聯的實例,僅支持hasMany關係
[options.include[].limit]Number限制連接的行數,僅在include.separate=true時支持
[options.include[]
.through.where]
Object爲 belongsToMany 關係,過濾連接的模型
[options.include[]
.through.attributes]
Array在 belongsToMany 關係中,連接模型選擇的屬性列表
[options.include[].include]Array.<Object | Model>進一步嵌套相關模型
[options.order]String | Array | Sequelize.fn指定一個排序. 如果是字符串,那麼會進行編碼。
如果是數組,那麼可以依次提供多組列名/排序函數,每一組包含兩個元素,第一個是排序字段名,第二個是排序方式,如: order: [['name', 'DESC']]。這種情況下,列名會進行編碼而排序方向不會
[options.limit]Number 
[options.offset]Number 
[options.transaction]Transaction在事務中執行查詢
[options.lock]String | Object鎖定已選行. 可選項有: transaction.LOCK.UPDATE、 transaction.LOCK.SHARE,
Postgres還支持: supports transaction.LOCK.KEY_SHARE、 transaction.LOCK.NO_KEY_UPDATE 和指定模型的連接鎖
詳見 transaction.LOCK
[options.raw]Boolean返回原始結果. 詳見 sequelize.query
[options.logging=false]Function一個用於打印執行SQL語句的函數
[options.having]Object 
[options
.searchPath=DEFAULT]
String一個用於指定 schema 的 search_path 的可選項(僅 Postgres 適用)
[options.benchmark=false]Boolean打印執行SQL語句時,同時輸出執行時間(毫秒)


3.9 findById() - 通過Id查詢單條數據

findById(id, [options]) -> Promise.<Instance>

通過Id(主鍵)查詢單個實例(單條數據)。

參數

名稱類型說明
idNumber | String | Buffer要查詢實例的主鍵
[options]Object 
[options.transaction]Transaction在事務中執行查詢
[options
.searchPath=DEFAULT]
String指定schema的 search_path (僅 Postgres)

別名:findByPrimary


3.10 findOne() - 通過單條數據

findById(id, [options]) -> Promise.<Instance>

查詢單個實例(單條數據)。這將會使用LIMIT 1查詢條件,所以回調中總是返回單個實例。

參數

名稱類型說明
[options]Object 
[options.transaction]Transaction在事務中執行查詢
[options.searchPath=DEFAULT]String指定schema的 search_path (僅 Postgres)


3.11 aggregate() - 聚合查詢

aggregate(field, aggregateFunction, [options]) -> Promise.<options.dataType|object>

在指定字段field上運行聚合查詢。

參數

名稱類型說明
fieldString要運行聚合的字段。可以是字段名或*
aggregateFunctionString聚合函數,如summaxetc.
[options]Object查詢選項,可通過sequelize.query查看所有選項
[options.where]Object查詢屬性
[options.logging=false]Function一個用於打印查詢時所執行sql的函數
[options.dataType]DataType | String結果類型。如field是模型中的字段,默認爲字段的類型,其它情況爲默認爲 float
[options.distinct]boolean爲字段使用DISTINCT聚合查詢
[options.transaction]Transaction在事務中運行查詢
[options.plain]Boolean當爲true時,第一個aggregateFunction的返回值爲dataType指定和返回,如果添加了額外的屬性,則由group分句決定。設置plain 爲 false 時會返回所有返回行中的所有值 。默認爲 true
[options.benchmark=false]Boolean當打印SQL日誌時同時輸出查詢執行時間(毫秒)


3.12 count() - 統計查詢結果數

count([options]) -> Promise.<Integer>

統計符合查詢條件的結果總數。

如果提供了include,將計算匹配關聯的數目

參數

名稱類型說明
[options]Object 
[options.where]Object查詢屬性(條件)
[options.include]ObjectInclude 選項
[options.distinct]boolean在主鍵上使用 COUNT(DISTINCT(col)), Model.aggregate 要使用其它列
[options.attributes]Object在 group中聯合使用
[options.group]Object創建複雜統計時,會返回所需要的多行
[options.transaction]Transaction在事務中執行查詢Transaction to run query under
[options.logging=false]Function一個用於打印查詢時所執行sql的函數
[options
.searchPath=DEFAULT]
String指定schema的 search_path (僅 Postgres)
[options.benchmark=false]Boolean當打印SQL日誌時同時輸出查詢執行時間(毫秒)


3.13 findAndCount() - 分頁查詢

findAndCount([findOptions]) -> Promise.<Object>

查詢由offset/limit指定的所有匹配行,並返回查詢條件所匹配的總數量。

Model.findAndCountAll({
  where: ...,
  limit: 12,
  offset: 12
}).then(function (result) {
  ...
})

在上面查詢中,result是一個包含以兩個屬性的對象:

{
  rows: [],
  count: 
}

result.rows是匹配的查詢行,result.count是查詢條件匹配的總數量。

如果提供了include,將計算匹配關聯的數目

User.findAndCountAll({
  include: [
     { model: Profile, required: true}
  ],
  limit 3
});

參數

名稱類型說明
[findOptions]Object參見 findAll

別名:findAndCountAll


3.14 max() - 查詢最大值

max(field, [options]) -> Promise.<Any>

查詢指定字段的最大值

參數

名稱類型說明
fieldString 
[options]Object參見 Object


3.15 min() - 查詢最大值

min(field, [options]) -> Promise.

查詢指定字段的最小值

參數

名稱類型說明
fieldString 
[options]Object參見 Object


3.16 sum() - 求和

sum(field, [options]) -> Promise.<Number>

對指定字段求和

參數

名稱類型說明
fieldString 
[options]Object參見 Object


3.17 build() - 創建新實例

build(values, [options]) -> Instance

創建一個新的模型實例,Values參數爲新例指定的鍵值對對象

參數

名稱類型說明
valuesObject 
[options]Object 
[options.raw=false]Boolean設置爲true時,值會忽略字段和虛擬設置器
[options.isNewRecord=true]Boolean 
[options.include]Array用於構建prefetched/included模型,參見 set


3.18 create() - 創建保存新實例

create(values, [options]) -> Promise.<Instance>

構建一個新的模型實例,並進行保存。與build()方法不同的是,此方法除創建新實例外,還會將其保存到對應數據庫表中。

參數

名稱類型說明
valuesObject 
[options]Object 
[options.raw=false]Boolean設置爲true時,值會忽略字段和虛擬設置器
[options.isNewRecord=true]Boolean 
[options.fields]Array如果設置後,只有列表中區別的列纔會進行保存
[options.include]Array用於構建prefetched/included模型,參見 set
[options.onDuplicate]String 
[options.transaction]Transaction在事務中執行查詢
[options.logging=false]Function一個用於打印查詢時所執行sql的函數
[options.searchPath=DEFAULT]String指定schema的 search_path (僅 Postgres)
[options.benchmark=false]Boolean當打印SQL日誌時同時輸出查詢執行時間(毫秒)


3.19 findOrInitialize() - 查找或初始化

findOrInitialize -> Promise.<Instance, initialized>

查找一行記錄,如果不存在則創建(不保存)實例

參數

名稱類型說明
optionsObject 
options.whereObject查詢屬性
[options.defaults]Object用於創建新實例的默認值
[options.transaction]Transaction在事務中執行查詢
[options.logging=false]Function一個用於打印查詢時所執行sql的函數
[options.searchPath=DEFAULT]String指定schema的 search_path (僅 Postgres)
[options.benchmark=false]Boolean當打印SQL日誌時同時輸出查詢執行時間(毫秒)

別名:findOrBuild


3.20 findOrCreate() - 查找或創建

findOrCreate(options) -> Promise.<Instance, created>

查找一行記錄,如果不存在則創建實例並保存到數據庫中

在這個方法中,如果options對象中沒有傳入事務,那麼會在內部自動創建一個新的事務,以防止在創建完成之前有新匹配查詢進入。

參數

名稱類型說明
optionsObject 
options.whereObject查詢屬性
[options.defaults]Object用於創建新實例的默認值
[options.transaction]Transaction在事務中執行查詢


3.21 findCreateFind() - 查找或創建

findCreateFind(options) -> Promise.<Instance, created>

效率更高的findOrCreate,不會在事務中執行。首先會嘗試進行查詢,如果爲空則嘗試創建,如果是唯一約束則嘗試再次查找。

參數

名稱類型說明
optionsObject 
options.whereObject查詢屬性
[options.defaults]Object用於創建新實例的默認值
[options.transaction]Transaction在事務中執行查詢


3.22 upsert() - 創建或更新

upsert(values, [options]) -> Promise.<created>

創建或更新一行。如果匹配到主鍵或唯一約束鍵時會進行更新。

執行詳細:

  • MySQL - 做爲單條查詢執行 INSERT values ON DUPLICATE KEY UPDATE values
  • PostgreSQL - 作爲一個臨時性的異常處理函數來實現: INSERT EXCEPTION WHEN unique_constraint UPDATE
  • SQLite - 做爲兩條查詢執行 INSERT; UPDATE。這意味着,無論該行是否存在都會進行更新

參數

名稱類型說明
valuesObject 
[options]Object 
[options.validate=true]Boolean插入前進行驗證
[options.fields=Object.keys(this.attributes)]Array要插入/更新字段。默認全部
[options.transaction]Transaction在事務中執行查詢

別名:insertOrUpdate


3.23 bulkCreate() - 創建多條記錄

bulkCreate(records, [options]) -> Promise.<Array.<Instance>>

批量創建並保存多個實例。

處理成功後,會在回調函數中返回一個包含多個實例的數組。

參數

名稱類型說明
recordsArray要創建實例的對象(鍵/值 對)列表
[options]Object 
[options.fields]Array要插入的字段。默認全部
[options.validate=true]Boolean插入每條記錄前進行驗證
[options.hooks=true]Boolean在執行前/後創建鉤子
[options.individualHooks=false]Boolean在執行前/後爲每個實例創建鉤子
[options.ignoreDuplicates=false]Boolean忽略重複主鍵(Postgres不支持)
[options.updateOnDuplicate]Array如果行鍵已存在是否更新(mysql & mariadb支持). 默認爲更新
[options.transaction]Transaction在事務中執行查詢


3.24 truncate() - 截斷模型

truncate([options]) -> Promise

截斷模型的所有實例,這個方法是Model.destroy({ truncate: true })便捷方法。

參數

名稱類型說明
recordsArray要創建實例的對象(鍵/值 對)列表
[options]Object 
[options.transaction]Transaction在事務中執行查詢
[options.cascade=false]Boolean | function僅適用於連接查詢時的TRUNCATE操作,截斷所有外鍵匹配的表


3.25 destroy() - 刪除記錄

destroy(options) -> Promise.<Integer>

刪除多個實例,或設置deletedAt的時間戳爲當前時間(當啓用paranoid時)

執行成功後返回被刪除的行數

參數

名稱類型說明
optionsObject 
[options.where]Object篩選條件
[options.hooks=true]Boolean在執行前/後創建鉤子
[options.individualHooks=false]Boolean在執行前/後爲每個實例創建鉤子
[options.limit]Number要刪除的行數
[options.force=false]Boolean刪除而不是設置 deletedAt 爲當前時間戳 (僅啓用 paranoid 時適用)
[options.truncate=false]Boolean設置爲true時,會使用TRUNCATE代替DELETE FROM,這時會忽略wherelimit選項
[options.cascade=false]Boolean僅適用於連接查詢時的TRUNCATE操作,截斷所有外鍵匹配的表
[options.transaction]Transaction在事務中執行查詢


3.26 restore() - 恢復記錄

restore(options) -> Promise.<undefined>

恢復多個實例,當啓用paranoid

參數

名稱類型說明
optionsObject 
[options.where]Object篩選條件
[options.hooks=true]Boolean在執行前/後創建鉤子
[options.individualHooks=false]Boolean在執行前/後爲每個實例創建鉤子
[options.limit]Number要恢復的行數
[options.transaction]Transaction在事務中執行查詢


3.27 update() - 更新記錄

update(values, options) -> Promise.<Array.<affectedCount, affectedRows>>

更新所匹配的多個實例。promise回調中會返回一個包含一個或兩個元素的數組,第一個元素始終表示受影響的行數,第二個元素表示實際影響的行(僅Postgreoptions.returning爲true時受支持)

參數

名稱類型說明
valuesObject 
optionsObject 
options.whereObject篩選條件
[options.fields]Array要更新字段,默認爲全部
[options.validate=true]Boolean更新每條記錄前進行驗證
[options.hooks=true]Boolean在執行更新前/後創建鉤子
[options.individualHooks=false]Boolean在執行更新前/後爲每個實例創建鉤子
[options.sideEffects=true]Boolean是否更新任何虛擬設置
[options.returning=false]Boolean返回受影響的行 (僅適用於 postgres)
[options.limit]Number要更新的行數 (僅適用於 mysql 和 mariadb)
[options.transaction]Transaction在事務中執行查詢
[options.silent=false]Boolean如果爲true,updatedAt字段將不會更新


3.28 describe() - 查詢表信息

describe() -> Promise

運行一個表的描述查詢,返回結果中將包含屬性及其類型:

let User = sequelize.define('user', {
  firstName: Sequelize.STRING,
  lastName: Sequelize.STRING
});

User.describe().then(function(result){
  console.log(result);
})
// 結果如下
{ id: 
   { type: 'INT(11)',
     allowNull: false,
     defaultValue: null,
     primaryKey: true },
  firstName: 
   { type: 'VARCHAR(255)',
     allowNull: true,
     defaultValue: null,
     primaryKey: false },
  lastName: 
   { type: 'VARCHAR(255)',
     allowNull: true,
     defaultValue: null,
     primaryKey: false }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章