實踐+源碼分析徹底理解 Sequelize,有詳細例子!!!

Sequelize 是一款優秀的數據庫 ORM 框架,支持 mysql、postgres、sqlite、mariadb、mssql。使用方法很是靈活多變,GitHub star 數目前 20k 左右,其周邊工具 sequelize-auto 可自動從數據庫生成模型文件,sequelize-cli 能夠依據模型文件建立數據庫,能力很是強大。html

上篇文章講解了 Sequelize 的基本使用,這篇文章從源碼角度的解析 Sequelize,讓你們用的明明白白!!node

連接mysql

以 mysql 爲例git

鏈接數據庫

npm i -S sequelize mysql2
複製代碼

實例化 Sequelize 進行鏈接,參數在構造函數中配置github

const Sequelize = require('sequelize');

// Option 1: Passing parameters separately
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql',
  // 額外的配置...
});

// Option 2: Passing a connection URI
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
複製代碼

Sequelize 構造函數解析

源碼中 Sequelize 構造函數,列舉經常使用的參數正則表達式

  • database string 數據庫名
  • username=null string 用戶名
  • password=null string 密碼
  • options={} Object 配置
  • options.host='localhost' string host 地址
  • options.port= number 數據庫 serve 端口
  • options.username=null string 用戶名,同上面用戶名
  • options.password=null string 密碼,同上面用戶名,只需傳其一
  • options.database=null string 數據庫名,同上
  • options.dialect string 要使用的數據庫類型,目前支持 mysql, postgres, sqlite, mssql.
  • timezone='+00:00' string 時區設置,默認中國時區須要變動爲"+08:00",若是有使用 NOW 函數必定要注意。The timezone used when converting a date from the database into a JavaScript date. The timezone is also used to SET TIMEZONE when connecting to the server, to ensure that the result of NOW, CURRENT_TIMESTAMP and other time related functions have in the right timezone. For best cross platform performance use the format +/-HH:MM. Will also accept string versions of timezones used by moment.js (e.g. 'America/Los_Angeles'); this is useful to capture daylight savings time changes.
  • options.logging=console.log Function A function that gets executed every time Sequelize would log something.
  • options.benchmark=false boolean Pass query execution time in milliseconds as second argument to logging function (options.logging).
  • options.replication=false boolean Use read / write replication. To enable replication, pass an object, with two properties, read and write. Write should be an object (a single server for handling writes), and read an array of object (several servers to handle reads). Each read/write server can have the following properties: host, port, username, password, database
  • options.pool Object 鏈接池配置
  • options.pool.max=5 number 鏈接池最大鏈接數
  • options.pool.min=0 number 鏈接池最小鏈接數
  • options.pool.idle=10000 number The maximum time, in milliseconds, that a connection can be idle before being released.閒置鏈接的最大存活時間
  • options.pool.acquire=60000 number The maximum time, in milliseconds, that pool will try to get connection before throwing error,出錯以後再次鏈接的最長時間
  • options.pool.evict=1000 number The time interval, in milliseconds, after which sequelize-pool will remove idle connections.多長時間以後將會移除閒置鏈接
  • options.operatorsAliases ObjectString based operator alias. Pass object to limit set of aliased operators.設置操做符別名
  • options.hooks Object 鏈接和斷開數據庫的一些鉤子函數。 An object of global hook functions that are called before and after certain lifecycle events. Global hooks will run after any model-specific hooks defined for the same event (See Sequelize.Model.init() for a list). Additionally, beforeConnect(), afterConnect(), beforeDisconnect(), and afterDisconnect() hooks may be defined here.

最簡化的鏈接

// src/db/index.js
const Sequelize = require('sequelize');

const sequelize = new Sequelize('testdb', 'root', 'root', {
  host: 'localhost',
  port: 8889, // 默認是 3306,個人電腦設置的 8889
  dialect: 'mysql',
});

module.exports = sequelize;


// App.js
const seq = require('./src/db');

seq
  .authenticate()
  .then(() => {
    console.log('Connection has been established successfully.');
  })
  .catch(err => {
    console.error('Unable to connect to the database:', err);
  });
  
// node App.js
複製代碼

鏈接成功則打印以下sql

數據庫模型

Sequelize 須要創建模型,才能夠對數據庫進行操做,對數據庫的每一個表創建模型文件太過繁瑣。 可使用 sequelize-auto 從數據庫直接導出模型。typescript

先建立數據庫 testdb,執行 sql 語句自動建表 testdb數據庫

安裝 sequelize-autonpm

npm i -D sequelize-auto
複製代碼

自動從數據庫導出模型

sequelize-auto 使用

[node] sequelize-auto -h <host> -d <database> -u <user> -x [password] -p [port]  --dialect [dialect] -c [/path/to/config] -o [/path/to/models] -t [tableName] -C

Options:
  -h, --host        IP/Hostname for the database.   [required]
  -d, --database    Database name.                  [required]
  -u, --user        Username for database.
  -x, --pass        Password for database.
  -p, --port        Port number for database.
  -c, --config      JSON file for Sequelize's constructor "options" flag object as defined here: https://sequelize.readthedocs.org/en/latest/api/sequelize/
  -o, --output      What directory to place the models.
  -e, --dialect     The dialect/engine that you're using: postgres, mysql, sqlite
  -a, --additional  Path to a json file containing model definitions (for all tables) which are to be defined within a model's configuration parameter. For more info: https://sequelize.readthedocs.org/en/latest/docs/models-definition/#configuration
  -t, --tables      Comma-separated names of tables to import
  -T, --skip-tables Comma-separated names of tables to skip
  -C, --camel       Use camel case to name models and fields
  -n, --no-write    Prevent writing the models to disk.
  -s, --schema      Database schema from which to retrieve tables
  -z, --typescript  Output models as typescript with a definitions file.
複製代碼

簡單配置

// package.json
"scripts": {
  "sequelize": "sequelize-auto -o ./src/db/model -d testdb -h localhost -u root -p 8889 -x root -e mysql"
},
複製代碼

自動生成的模型以下

// src/db/model/blog.js
/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('blog', {
    id: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
    },
    school: {
      type: DataTypes.STRING(255),
      allowNull: true
    },
    name: {
      type: DataTypes.STRING(255),
      allowNull: true
    }
  }, {
    tableName: 'blog',
    timestamps: false,
  });
};


// src/db/model/users.js
/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('users', {
    id: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
    },
    name: {
      type: DataTypes.STRING(30),
      allowNull: true
    },
    age: {
      type: DataTypes.INTEGER(11),
      allowNull: true
    },
    created_at: {
      type: DataTypes.DATE,
      allowNull: true
    },
    updated_at: {
      type: DataTypes.DATE,
      allowNull: true
    }
  }, {
    tableName: 'users',
    timestamps: false,
  });
};

複製代碼

sequelize.definemodel.init

源碼中 define 定義以下,它實際就是 model.initdefine 的三個參數被放到了 init 中。

define 上面有這句話,當 model 被 define 定義好以後,能夠經過 sequelize.models.modelName 來執行數據庫操做!!!

/** * Define a new model, representing a table in the database. * * The table columns are defined by the object that is given as the second argument. Each key of the object represents a column * * @param {string} modelName The name of the model. The model will be stored in `sequelize.models` under this name * @param {Object} attributes An object, where each attribute is a column of the table. See {@link Model.init} * @param {Object} [options] These options are merged with the default define options provided to the Sequelize constructor and passed to Model.init() * * @see * {@link Model.init} for a more comprehensive specification of the `options` and `attributes` objects. * @see <a href="/manual/tutorial/models-definition.html">Model definition</a> Manual related to model definition * @see * {@link DataTypes} For a list of possible data types * * @returns {Model} Newly defined model * * @example * sequelize.define('modelName', { * columnA: { * type: Sequelize.BOOLEAN, * validate: { * is: ["[a-z]",'i'], // will only allow letters * max: 23, // only allow values <= 23 * isIn: { * args: [['en', 'zh']], * msg: "Must be English or Chinese" * } * }, * field: 'column_a' * }, * columnB: Sequelize.STRING, * columnC: 'MY VERY OWN COLUMN TYPE' * }); * * sequelize.models.modelName // The model will now be available in models under the name given to define */
  define(modelName, attributes, options = {}) {
    options.modelName = modelName;
    options.sequelize = this;

    const model = class extends Model {};

    model.init(attributes, options);

    return model;
  }
複製代碼

模型字段定義 DataTypes

DataTypes

CHAR

Sequelize.CHAR(100)                   // CHAR(100)
Sequelize.STRING                      // VARCHAR(255)
Sequelize.STRING(1234)                // VARCHAR(1234)
Sequelize.TEXT                        // TEXT
Sequelize.TEXT('tiny')                // TINYTEXT
複製代碼

NUMBER

Sequelize.TINYINT                     // TINYINT
Sequelize.SMALLINT                    // SMALLINT
Sequelize.MEDIUMINT                   // MEDIUMINT
Sequelize.INTEGER                     // INTEGER
Sequelize.BIGINT                      // BIGINT
Sequelize.BIGINT(11)                  // BIGINT(11)

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

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

Sequelize.DECIMAL                     // DECIMAL
Sequelize.DECIMAL(10, 2)              // DECIMAL(10,2)
複製代碼

TIME

Sequelize.DATE                        // mysql / sqlite 爲 DATETIME, postgres 爲帶時區的 TIMESTAMP
Sequelize.DATE
Sequelize.TIME
Sequelize.DATEONLY                    // DATE 不帶時間.
複製代碼

BOOLEAN

Sequelize.BOOLEAN                     // TINYINT(1)
複製代碼

ENUM

Sequelize.ENUM('value 1', 'value 2')  // 一個容許值爲'value 1'和'value 2'的ENUM
複製代碼

blob

Sequelize.BLOB                        // BLOB (PostgreSQL 爲 bytea)
Sequelize.BLOB('tiny')                // TINYBLOB (PostgreSQL 爲 bytea. 其他參數是 medium 和 long)
複製代碼

GEOMETRY

Sequelize.GEOMETRY                    // Spatial 列. 僅 PostgreSQL (帶有 PostGIS) 或 MySQL.
Sequelize.GEOMETRY('POINT')           // 帶有 geometry 類型的 spatial 列. 僅 PostgreSQL (帶有 PostGIS) 或 MySQL.
Sequelize.GEOMETRY('POINT', 4326)     // 具備 geometry 類型和 SRID 的 spatial 列. 僅 PostgreSQL (帶有 PostGIS) 或 MySQL.
複製代碼

integer, bigint, floatdouble 還支持 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
複製代碼

源代碼 sequelize/lib/sequelize.js 中,將 DataTypes 總體導出的同時,還將全部 DataTypes 類型所有掛載在了 Sequelize 上,因此有如下兩種使用方式

const Sequelize, { DataTypes } = require('sequelize')

// ...
created_at: {
  type: Sequelize.DATE,
  allowNull: true
}
// or
created_at: {
  type: DataTypes.DATE,
  allowNull: true
}
複製代碼

每一個字段的全部定義方式以下

  • type string | DataTypes 字符串或者 DataType
  • allowNull=true boolean 容許 Null
  • defaultValue=null any 字段默認值
  • unique=false string | boolean 是否惟一索引,If true, the column will get a unique constraint. If a string is provided, the column will be part of a composite unique index. If multiple columns have the same string, they will be part of the same unique index
  • primaryKey=false boolean 是否爲主鍵,If true, this attribute will be marked as primary key
  • autoIncrement=false boolean 自增,If true, this column will be set to auto increment
  • comment=null string 字段註釋,Comment for this column
  • references=null string | Model An object with reference configurations
  • references.model string | Model If this column references another table, provide it here as a Model, or a string
  • references.key='id' string The column of the foreign table that this column references
  • validate Object 字段校驗,見屬性驗證器

模型參數配置

sequelize 模型須要手動配置一些參數 Configuration

其餘經常使用配置以下

  • timestamp=true boolean Sequelize 使用時會自動添加 createdAtupdatedAt 到模型中,若是表中沒有這兩個字段可是 timestamp=true,則會報錯,須要在模型定義中指定爲 false
  • freezeTableName=false boolean Sequelize 默認會將全部的表名變動爲複數,若是不想被自動變動,須要設置爲 true
  • modelName string 模型名,默認是類名,以下代碼
  • paranoid=false boolean 調用 destroy 不會刪除記錄,可是會設置 deletedAt 字段爲當前的時間戳若是 paranoid=true,須要 timestamps=true纔會走這個邏輯
  • underscored=false``boolean 不使用駝峯式命令規則,這樣會在使用下劃線分隔,updatedAt 的字段名會是 updated_at
  • tableName string 表名,freezeTableName=false 會讓表名自動編程複數
  • engine string 表的引擎,默認爲 InnoDB
  • sequelize Object 給模型傳入 sequelize 實例(new Sequelize(xxx)),不傳入將會報錯
class Bar extends Model {}
Bar.init({ /* bla */ }, {
  // The name of the model. The model will be stored in `sequelize.models` under this name.
  // This defaults to class name i.e. Bar in this case. This will control name of auto-generated
  // foreignKey and association naming
  modelName: 'bar',

  // don't add the timestamp attributes (updatedAt, createdAt)
  timestamps: false,

  // don't delete database entries but set the newly added attribute deletedAt
  // to the current date (when deletion was done). paranoid will only work if
  // timestamps are enabled
  paranoid: true,

  // Will automatically set field option for all attributes to snake cased name.
  // Does not override attribute with field option already defined
  underscored: true,

  // disable the modification of table names; By default, sequelize will automatically
  // transform all passed model names (first parameter of define) into plural.
  // if you don't want that, set the following
  freezeTableName: true,

  // define the table's name
  tableName: 'my_very_custom_table_name',

  // Enable optimistic locking. When enabled, sequelize will add a version count attribute
  // to the model and throw an OptimisticLockingError error when stale instances are saved.
  // Set to true or a string with the attribute name you want to use to enable.
  version: true,

  // Sequelize instance
  sequelize,
})
複製代碼

註冊 model 到 sequelize 實例

前面咱們已經配置好了模型,創建好了數據鏈接,獲得 sequelize 實例和模型文件,這步咱們使用 sequelize.import 進行註冊。

import 方法會對註冊的 model 進行緩存,重複註冊相同 model 不會有效果。它能夠將 sequelize-auto 導出的 model 文件直接進行註冊。

官方文檔

源碼定義,源碼主要看 if (!this.importCache[importPath]) { 後面的,就是把 model 放到 this.importCache


咱們來實戰演示

基於數據庫導出的 usersblog 兩個 model,對 model 作如下更改,阻止默認行爲

// src/db/model/blog.js
{
  tableName: 'blog',
  timestamps: false,
}

// src/db/model/users.js
{
  tableName: 'users',
  timestamps: false,
}
複製代碼

修改 index.js

// src/db/index.js
const Sequelize = require('sequelize');
const fs = require('fs');
const path = require('path');
const sequelize = new Sequelize('testdb', 'root', 'root', {
  host: 'localhost',
  port: 8889,
  dialect: 'mysql',
});
// model 目錄絕對路徑
const modelPath = path.resolve(__dirname, './model');
// 讀取全部 model 文件
const files = fs.readdirSync(modelPath);
const db = {};
// 將 model 掛到 db 上
files.forEach(fileName => {
  const modelName = fileName.slice(0, -3);
  db[modelName] = sequelize.import(path.resolve(modelPath, fileName));
});
module.exports = db;
複製代碼

App.js

const db = require('./src/db');
async function init() {
  const users = await db.users.findAll();
  const blog = await db.blog.findAll();
  console.log(JSON.parse(JSON.stringify(users)));
  console.log(JSON.parse(JSON.stringify(blog)));
}
init();
複製代碼

執行結果

注意到沒有,咱們的 App.js 正常應該執行完 node 就會退出,可是這裏 node 是在 10 秒多以後才退出,由於鏈接池的閒置鏈接沒有被回收。

更改 idle (閒置鏈接回收時間)

知道以上 sequelize 註冊方式以後,能夠很容易地把它嵌入到現有的 nodejs 框架中,掛載到上下文對象上便可在各個地方訪問。

數據庫操做

操做方法

Model 操做方法

create

建立一條記錄,並返回這條數據庫記錄

public static create(values: Object, options: Object): Promise<Model>
複製代碼

src/db/model/users.js 更改以下

created_at: {
  type: DataTypes.DATE,
  allowNull: true,
  defaultValue: sequelize.fn('NOW') // 填充默認時間爲如今
},
updated_at: {
  type: DataTypes.DATE,
  allowNull: true,
  defaultValue: sequelize.fn('NOW') // 填充默認時間爲如今
}
複製代碼
// App.js
const users = await db.users.create({
  name: 'lxfriday',
  age: 33,
});
console.log(JSON.parse(JSON.stringify(users)));
複製代碼

插入以後返回記錄

注意時區問題,在本篇文章最開始鏈接數據庫的時候 options.timezone 設爲 +08:00 便可變動爲中國時間。

bulkCreate

建立多條記錄,並返回一個一個對象數組,每一個對象是一條記錄

public static bulkCreate(records: Array, options: Object): Promise<Array<Model>>
複製代碼
const users = await db.users.bulkCreate([
    {
      name: 'lxfriday1',
      age: 111,
    },
    {
      name: 'lxfriday2',
      age: 222,
    },
    {
      name: 'lxfriday3',
      age: 338,
    },
  ]);
複製代碼

findOrCreate

先查找,沒有找到則依據條件進行建立

public static findOrCreate(options: Object): Promise<Model, boolean>
複製代碼

const users = await db.users.findOrCreate({
  where: {
    name: 'lxfridaysss',
    age: 3399,
  },
});
const users2 = await db.users.findOrCreate({
  where: {
    name: 'lxfridaywww',
  },
  defaults: {
    age: 3399,
  }
});
// 會自動合併成{name,age}
複製代碼

沒有找到的時候,會自動將 where 和 defaults 合併做爲新的數據源

findAll

按條件查詢全部

public static findAll(options: Object): Promise<Array<Model>>
複製代碼

主要注意查詢條件和查詢字段,操做符從 Sequelize.Op 導出。

  • where Object 查詢條件
  • attributes Array<string> | Object 查詢的字段
  • attributes.include Array<string> 要包括的字段,同直接給 attributes 賦值
  • attributes.exclude Array<string> 不要要包括的字段
  • order Array | fn | col | literal 排序,[['id', 'DESC'], 'age']
['age', 'DESC'],
// ['id', 'ASC'],
'id',// 同上
複製代碼
  • limit number 限制查詢條數
  • offset number 偏移量
![](https://user-gold-cdn.xitu.io/2019/7/28/16c3936efb0f7f3e?w=548&h=501&f=png&s=62216)
複製代碼
await db.users.findAll({
  where: {
    attr1: 42,
    attr2: 'cake'
  }
})
// WHERE attr1 = 42 AND attr2 = 'cake'
複製代碼
const users = await db.users.findAll({
    attributes: {
      exclude: ['name']
    },
    where: {
      name: {
        [like]: '%lxfriday%',
      },
    },
    order: [
      ['age', 'DESC'],
      ['id', 'ASC'],
      // 'id',
    ],
  });
複製代碼

執行語句和結果

const {gt, lte, ne, in: opIn} = Sequelize.Op;

await db.users.findAll({
  where: {
    attr1: {
      [gt]: 50
    },
    attr2: {
      [lte]: 45
    },
    attr3: {
      [opIn]: [1,2,3]
    },
    attr4: {
      [ne]: 5
    }
  }
})

// WHERE attr1 > 50 AND attr2 <= 45 AND attr3 IN (1,2,3) AND attr4 != 5
複製代碼
const {or, and, gt, lt} = Sequelize.Op;

await db.users.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));
複製代碼
findOne

查找一條,是 findAll({limit: 1, ...}) 版本,配置見 findAll

public static findOne(options: Object): Promise<Model>
複製代碼

findByPk
public static findByPk(param: number | string | Buffer, options: Object): Promise<Model>
複製代碼

按主鍵進行查詢,主鍵能夠是任何任意字段和類型,不只僅是 id 才能當主鍵

blog_url 是主鍵

findAndCountAll

查到並統計結果數

public static findAndCountAll(options: Object): Promise<{count: number, rows: Model[]}>
複製代碼

update

更改數據

public static update(values: Object, options: Object): Promise<Array<number, number>>
複製代碼

返回一個數組,數組的參數是被修改的條數

upsert

更新,不存在則建立一條記錄

public static upsert(values: Object, options: Object): Promise<boolean>
複製代碼

public static destroy(options: Object): Promise<number>
複製代碼

統計

count
public static count(options: Object): Promise<number>
複製代碼
min、max、sum

field 要查詢的字段

public static min(field: string, options: Object): Promise<*>
複製代碼

聚合查詢

aggregate
public static aggregate(attribute: string, aggregateFunction: string, options: Object): Promise<DataTypes|Object>
複製代碼

操做符

sequelize.Op 導出,

const Op = Sequelize.Op

[Op.and]: {a: 5}           // 且 (a = 5)
[Op.or]: [{a: 5}, {a: 6}]  // (a = 5 或 a = 6)
[Op.gt]: 6,                // id > 6
[Op.gte]: 6,               // id >= 6
[Op.lt]: 10,               // id < 10
[Op.lte]: 10,              // id <= 10
[Op.ne]: 20,               // id != 20
[Op.eq]: 3,                // = 3
[Op.not]: true,            // 不是 TRUE
[Op.between]: [6, 10],     // 在 6 和 10 之間
[Op.notBetween]: [11, 15], // 不在 11 和 15 之間
[Op.in]: [1, 2],           // 在 [1, 2] 之中
[Op.notIn]: [1, 2],        // 不在 [1, 2] 之中
[Op.like]: '%hat',         // 包含 '%hat'
[Op.notLike]: '%hat'       // 不包含 '%hat'
[Op.iLike]: '%hat'         // 包含 '%hat' (不區分大小寫) (僅限 PG)
[Op.notILike]: '%hat'      // 不包含 '%hat' (僅限 PG)
[Op.startsWith]: 'hat'     // 相似 'hat%'
[Op.endsWith]: 'hat'       // 相似 '%hat'
[Op.substring]: 'hat'      // 相似 '%hat%'
[Op.regexp]: '^[h|a|t]'    // 匹配正則表達式/~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.notRegexp]: '^[h|a|t]' // 不匹配正則表達式/!~ '^[h|a|t]' (僅限 MySQL/PG)
[Op.iRegexp]: '^[h|a|t]'    // ~* '^[h|a|t]' (僅限 PG)
[Op.notIRegexp]: '^[h|a|t]' // !~* '^[h|a|t]' (僅限 PG)
[Op.like]: { [Op.any]: ['cat', 'hat']} // 包含任何數組['cat', 'hat'] - 一樣適用於 iLike 和 notLike
[Op.overlap]: [1, 2]       // && [1, 2] (PG數組重疊運算符)
[Op.contains]: [1, 2]      // @> [1, 2] (PG數組包含運算符)
[Op.contained]: [1, 2]     // <@ [1, 2] (PG數組包含於運算符)
[Op.any]: [2,3]            // 任何數組[2, 3]::INTEGER (僅限PG)

[Op.col]: 'user.organization_id' // = 'user'.'organization_id', 使用數據庫語言特定的列標識符, 本例使用 PG
複製代碼

廣告時間

歡迎關注,每日進步!!!

相關文章
相關標籤/搜索