Sequelize-nodejs-2-basic usage
Basic usage基本使用
To get the ball rollin' you first have to create an instance of Sequelize. Use it the following way:
使用Sequelize的您必须首先创建一个实例。以下方式使用它:
const sequelize = new Sequelize('database', 'username', 'password', {
dialect: 'mysql'
});
This will save the passed database credentials and provide all further methods.
这将保存通过的数据库证书并提供所有进一步的方法。
Furthermore you can specify a non-default host/port:
此外您可以指定一个非默认主机/端口,下面是三种连接的方式,使用第一种:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('token', 'root', 'mypassword', {
dialect: 'mysql',//连接的数据库类型
// host: "127.0.0.1",//数据库地址
// port: 3306,//数据库接口
});
If you just don't have a password:
const sequelize = new Sequelize({
database: 'db_name',
username: 'username',
password: null,
dialect: 'mysql'
});
You can also use a connection string:
const sequelize = new Sequelize('mysql://user:pass@example.com:9821/db_name', {
// Look to the next section for possible options
})
Options
Besides the host and the port, Sequelize comes with a whole bunch of options. Here they are:
除了主机和端口,Sequelize有很多options
- See Sequelize API
- See Model Definition
- See Transactions
const sequelize = new Sequelize('database', 'username', 'password', {
// the sql dialect of the database
// currently supported: 'mysql', 'sqlite', 'postgres', 'mssql'
dialect: 'mysql',
// 自定义的host或者默认的localhost
host: 'my.server.tld',
// 自定义的端口,或者默认的,mysql默认的端口为3306
port: 12345,
// 自定义的协议,默认的为'tcp'
// postgres only, useful for Heroku
protocol: null,
// 禁用日志记录,默认使用console.log
logging: false,
// you can also pass any dialect options to the underlying dialect library
// - default is empty
// - currently supported: 'mysql', 'postgres', 'mssql'
dialectOptions: {
socketPath: '/Applications/MAMP/tmp/mysql/mysql.sock',
supportBigNumbers: true,
bigNumberStrings: true
},
// the storage engine for sqlite
// - default ':memory:'
storage: 'path/to/database.sqlite',
// 禁用插入未定义的值为null
// - default: false
omitNull: true,
// 是否使用一个本地库.
// in the case of 'pg' -- set this to true will allow SSL support
// - default: false
native: true,
// Specify options, which are used when sequelize.define is called.
// The following example:
// define: { timestamps: false }
// is basically the same as:
// sequelize.define(name, attributes, { timestamps: false })
// so defining the timestamps for each model will be not necessary
define: {
underscored: false
freezeTableName: false,
charset: 'utf8',
dialectOptions: {
collate: 'utf8_general_ci'
},
timestamps: true
},
// 类似的同步:您可以定义这个总是强迫使用同步模型
sync: { force: true },
// pool configuration used to pool database connections
pool: {
max: 5,//连接池中最大连接数量
idle: 30000,
acquire: 60000,//如果一个线程 60 秒钟内没有被使用过的话,那么就释放线程
},
// isolation level of each transaction
// defaults to dialect default
isolationLevel: Transaction.ISOLATION_LEVELS.REPEATABLE_READ
})
Hint: You can also define a custom function for the logging part. Just pass a function. The first parameter will be the string that is logged.您还可以定义一个自定义的日志函数。仅仅通过一个函数。第一个参数是被记录的字符串
Read replication
Sequelize supports read replication, i.e. having multiple servers that you can connect to when you want to do a SELECT query. When you do read replication, you specify one or more servers to act as read replicas, and one server to act as the write master, which handles all writes and updates and propagates them to the replicas (note that the actual replication process is not handled by Sequelize, but should be set up by database backend).
Sequelize支持读复制,即当你想做一个SELECT查询有多个服务器可以连接。当你读复制,您指定一个或多个服务器作为读副本,和一个服务器充当主写,用来处理所有写和更新并将它们传递到副本(请注意,实际的复制过程不是由Sequelize,但应该被数据库后端建立)
const sequelize = new Sequelize('database', null, null, {
dialect: 'mysql',
port: 3306
replication: {
read: [
{ host: '8.8.8.8', username: 'read-username', password: 'some-password' },
{ host: '9.9.9.9', username: 'another-username', password: null }
],
write: { host: '1.1.1.1', username: 'write-username', password: 'any-password' }
},
pool: { // If you want to override the options used for the read/write pool you can do so here
max: 20,
idle: 30000
},
})
If you have any general settings that apply to all replicas you do not need to provide them for each instance. In the code above, database name and port is propagated to all replicas. The same will happen for user and password, if you leave them out for any of the replicas. Each replica has the following options:host
,port
,username
,password
,database
.
如果你有任何一般设置适用于所有副本,那么你就不需要为每个实例一一提供设置。在上面的代码中,数据库名称和端口传播到所有副本。如果你离开任何副本,用户名和密码也会一样传播。每个副本都有以下选项:host
,port
,username
,password
,database
Sequelize uses a pool to manage connections to your replicas. Internally Sequelize will maintain two pools created using pool
configuration.
Sequelize使用池来管理连接到您的副本。内部Sequelize将保持通过使用池配置进行创建的两个池。
If you want to modify these, you can pass pool as an options when instantiating Sequelize, as shown above.
如果你想修改这些,当实例化Sequelize时,你可以把池作为一个选项,如上所示。
Each write
or useMaster: true
query will use write pool. For SELECT
read pool will be used. Read replica are switched using a basic round robin scheduling.
每个write
或useMaster:真正的查询将使用写池。对于SELECT命令,
读池将被使用。读副本将使用一个基本的轮循调度。
Dialects
With the release of Sequelize 1.6.0
, the library got independent from specific dialects. This means, that you'll have to add the respective connector library to your project yourself.
MySQL
In order to get Sequelize working nicely together with MySQL, you'll need to install mysql2@^1.0.0-rc.10
or higher. Once that's done you can use it like this:
在上面安装处也有说过,如果想要和mysql一起使用,必须安装mysql2@^1.0.0-rc.10模块
或者更高的版本
const sequelize = new Sequelize('database', 'username', 'password', {
dialect: 'mysql'
})
Note: You can pass options directly to dialect library by setting the dialectOptions
parameter. See Options for examples (currently only mysql is supported).
注意:您可以通过设置dialectOptions参数直接传递options给dialect库。
SQLite
For SQLite compatibility you'll need sqlite3@~3.0.0
. Configure Sequelize like this:
同时SQLite需要安装sqlite3@~3.0.0
const sequelize = new Sequelize('database', 'username', 'password', {
// sqlite! now!
dialect: 'sqlite',
// the storage engine for sqlite
// - default ':memory:'
storage: 'path/to/database.sqlite'
})
Or you can use a connection string as well with a path:
或者可以使用带着路径的连接字符串的形式
const sequelize = new Sequelize('sqlite:/home/abs/path/dbname.db')
const sequelize = new Sequelize('sqlite:relativePath/dbname.db')
PostgreSQL
The library for PostgreSQL is pg@^5.0.0 || ^6.0.0
You'll just need to define the dialect:
需要安装pg@^5.0.0 或 ^6.0.0版本
const sequelize = new Sequelize('database', 'username', 'password', {
// gimme postgres, please!
dialect: 'postgres'
})
MSSQL
The library for MSSQL is tedious@^1.7.0
You'll just need to define the dialect:
需要安装tedious@^1.7.0
const sequelize = new Sequelize('database', 'username', 'password', {
dialect: 'mssql'
})
Executing raw SQL queries执行原始SQL查询
As there are often use cases in which it is just easier to execute raw / already prepared SQL queries, you can utilize the function sequelize.query
.
在经常使用的情况下,执行原始/已经准备好的SQL查询是十分容易的,你可以使用函数sequelize.query
- See Sequelize.query API
- See Query Types
Here is how it works:
// 原始查询的参数
sequelize.query('your query', [, options])
// Quick example,例子
sequelize.query("SELECT * FROM myTable").then(myTableRows => {
console.log(myTableRows)
})
// 如果你想返回使用模型选项的sequelize实例.
// 这使您可以轻松地将一个查询映射到sequelize的预定义模型
.query('SELECT * FROM projects', { model: Projects })
.then(projects => {
// 每个记录将被映射到项目的model.
console.log(projects)
})
// Options is an object with the following keys:
sequelize
.query('SELECT 1', {
// 每一次SQL查询都会调用记录查询的函数并返给服务器
logging: console.log,
// 如果plain是true的,那么sequelize将只返回第一个记录的结果集
// 如果是false则返回所以记录
plain: false,
// 设置为真,如果你没有为你查询设置一个模型定义
raw: false,
//您正在执行的查询类型。查询类型影响如何在结果传回之前对其进行格式化
type: Sequelize.QueryTypes.SELECT
})
// 第二个参数为null
// Even if we declared a callee here, the raw: true would
// supersede and return a raw object.即使我们声明了一个被调用者,raw: true将取代并返回一个原始对象
sequelize
.query('SELECT * FROM projects', { raw: true })
.then(projects => {
console.log(projects)
})
Replacements in a query can be done in two different ways, either using named parameters (starting with :
), or unnamed, represented by a ?
替换查询中可以通过两种不同的方式,使用命名参数(以:开始),或匿名,以?表示
The syntax used depends on the replacements option passed to the function:
使用的语法取决于传递给函数的替代选项
- If an array is passed,
?
will be replaced in the order that they appear in the array如果通过的是数组,?将会按照他们在数组中出现的顺序来进行替换 - If an object is passed,
:key
will be replaced with the keys from that object. If the object contains keys not found in the query or vice versa, an exception will be thrown.如果通过的是对象,:key将会被对象中的keys值替换。如果在查询中包含keys的对象没有被找到,将会抛出一个异常;反之亦然。
sequelize
.query(
'SELECT * FROM projects WHERE status = ?',
{ raw: true, replacements: ['active']
)
.then(projects => {
console.log(projects)
})
sequelize
.query(
'SELECT * FROM projects WHERE status = :status ',
{ raw: true, replacements: { status: 'active' } }
)
.then(projects => {
console.log(projects)
})
One note: If the attribute names of the table contain dots, the resulting objects will be nested:
如果表的属性名称包含点,由此产生的对象将被嵌套
sequelize.query('select 1 as `foo.bar.baz`').then(rows => {
console.log(JSON.stringify(rows))
/*
[{
"foo": {
"bar": {
"baz": 1
}
}
}]
*/
})
举一个简单的例子,连接的是mysql:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('token', 'root', 'user78', {
dialect: 'mysql',
//默认host和port
// host: "127.0.0.1",
// port: 3306,
});
sequelize.query("SELECT * FROM user").then(myTableRows => {
console.log(myTableRows)
})
返回:
userdeMacBook-Pro:test-sequelize user$ node index.js
sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules/sequelize/lib/sequelize.js:242:13
Executing (default): SELECT * FROM user
[ [ TextRow { username: '1', id: 1, password: '1' },
TextRow { username: '12', id: 12, password: '2' },
TextRow { username: 'name', id: 13, password: '1231' },
TextRow { username: 'admin11', id: 21, password: '1111' },
TextRow { username: 'admin11111s', id: 22, password: '1111' },
TextRow { username: 'admin11111s', id: 23, password: 'aa' },
TextRow { username: 'user', id: 24, password: 'user' } ],
[ TextRow { username: '1', id: 1, password: '1' },
TextRow { username: '12', id: 12, password: '2' },
TextRow { username: 'name', id: 13, password: '1231' },
TextRow { username: 'admin11', id: 21, password: '1111' },
TextRow { username: 'admin11111s', id: 22, password: '1111' },
TextRow { username: 'admin11111s', id: 23, password: 'aa' },
TextRow { username: 'user', id: 24, password: 'user' } ] ]
警告:
sequelize deprecated String based operators are now deprecated. Please use Symbol based operators for better security, read more at http://docs.sequelizejs.com/manual/tutorial/querying.html#operators node_modules/sequelize/lib/sequelize.js:242:13
上面警告要解决的问题是:
Let me distill this regardless, Most web frameworks in Node.js allow parsing a object like string to actual JS object. This becomes a major issue when developers are passing user input without sanitizing them to Sequelize methods.
大多数web框架在nodejs允许解析字符串变为实际js对象这样的对象。这就变成了一个主要问题当开发人员通过用户输入没有对Sequelize方法进行处理
For example, consider this sample of code比如
db.Token.findOne({
where: {
token: req.query.token
}
);
Now a bad actor could pass token='{"$gt": 1}'
which will make above query to become something like this
这是传入token='{"$gt": 1}'则会将查询变为:
db.Token.findOne({
where: {
token: {
$gt: 1
}
}
);
This is because $gt
is a string based operator which can be injected as string. To mitigate this we introduced secure operators #8240
这是因为基于操作符的字符串将会被检测成字符串,为了解决这样的问题,我们将介绍安全操作符
Secure operators are Symbols which can't be duplicated by such object conversion. If we were using above code with secure operators we get this state 安全操作符都是Symbols对象,是不能被这样的对象转换复制的。如果我们使用上面带有安全操作符的代码,我们将得到了这种状态:
db.Token.findOne({
where: {
token: {
$gt: 1 // invalid, as Op.gt is an operator but $gt is not. This will throw an error
}
}
);
是无效的,Op.gt才是操作符,而$gt不是,所以会抛出错误
那么什么是安全操作符:
http://docs.sequelizejs.com/manual/tutorial/querying.html#operators-security
Operators Aliases操作符别名
Sequelize allows setting specific strings as aliases for operators
Sequelize允许为操作符设置特殊的字符串作为别名,比如:
const Op = Sequelize.Op;
const operatorsAliases = {
$gt: Op.gt
}
const connection = new Sequelize(db, user, pass, { operatorsAliases })
[Op.gt]: 6 // > 6
$gt: 6 // same as using Op.gt (> 6)
Operators security操作符安全性
Using Sequelize without any aliases improves security. Some frameworks automatically parse user input into js objects and if you fail to sanitize your input it might be possible to inject an Object with string operators to Sequelize.
使用没有任何别名的Sequelize提高了安全性。有些框架自动解析用户输入到js对象如果你未能清洁你的输入有可能注入Sequelize对象和字符串运算符
Not having any string aliases will make it extremely unlikely that operators could be injected but you should always properly validate and sanitize user input.
向后兼容性原因Sequelize默认设置下面的别名 - $eq, $ne, $gte, $gt, $lte, $lt, $not, $in, $notIn, $is, $like, $notLike, $iLike, $notILike, $regexp, $notRegexp, $iRegexp, $notIRegexp, $between, $notBetween, $overlap, $contains, $contained, $adjacent, $strictLeft, $strictRight, $noExtendRight, $noExtendLeft, $and, $or, $any, $all, $values, $col
目前以下遗留别名也被设置,但计划在不久的将来被完全移除 - ne, not, in, notIn, gte, gt, lte, lt, like, ilike, $ilike, nlike, $notlike, notilike, .., between, !.., notbetween, nbetween, overlap, &&, @>, <@For better security it is highly advised to use Sequelize.Op
and not depend on any string alias at all. You can limit alias your application will need by setting operatorsAliases
option, remember to sanitize user input especially when you are directly passing them to Sequelize methods.
为了更好的安全,强烈建议使用Sequelize.Op
和不依赖于任何字符串的别名。你可以通过设置别名operatorsAliases选项来限制你的应用程序需要的别名,记得要检查用户输入特别是当你直接传递他们给Sequelize的方法。
const Op = Sequelize.Op;
//use sequelize without any operators aliases,不使用别名
const connection = new Sequelize(db, user, pass, { operatorsAliases: false });
//use sequelize with only alias for $and => Op.and,只使用Op.and一个别名
const connection2 = new Sequelize(db, user, pass, { operatorsAliases: { $and: Op.and } });
Sequelize will warn you if you're using the default aliases and not limiting them if you want to keep using all default aliases (excluding legacy ones) without the warning you can pass the following operatorsAliases option -
如果你使用默认的别名并没有进行限制,Sequelize会警告你,所以我得到了上面的警告。
如果你想继续使用所有缺省别名(不包括遗留的)没有警告,您可以通过设置以下operatorsAliases选项:
const Op = Sequelize.Op;
const operatorsAliases = {
$eq: Op.eq,
$ne: Op.ne,
$gte: Op.gte,
$gt: Op.gt,
$lte: Op.lte,
$lt: Op.lt,
$not: Op.not,
$in: Op.in,
$notIn: Op.notIn,
$is: Op.is,
$like: Op.like,
$notLike: Op.notLike,
$iLike: Op.iLike,
$notILike: Op.notILike,
$regexp: Op.regexp,
$notRegexp: Op.notRegexp,
$iRegexp: Op.iRegexp,
$notIRegexp: Op.notIRegexp,
$between: Op.between,
$notBetween: Op.notBetween,
$overlap: Op.overlap,
$contains: Op.contains,
$contained: Op.contained,
$adjacent: Op.adjacent,
$strictLeft: Op.strictLeft,
$strictRight: Op.strictRight,
$noExtendRight: Op.noExtendRight,
$noExtendLeft: Op.noExtendLeft,
$and: Op.and,
$or: Op.or,
$any: Op.any,
$all: Op.all,
$values: Op.values,
$col: Op.col
};
const connection = new Sequelize(db, user, pass, { operatorsAliases });
解决警告的办法:
所以我们最好的解决上面的警告的方法就是添加别名定义,将之前的例子改成下面的样子,警告将消失:
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
const operatorsAliases = {
$eq: Op.eq,
$ne: Op.ne,
$gte: Op.gte,
$gt: Op.gt,
$lte: Op.lte,
$lt: Op.lt,
$not: Op.not,
$in: Op.in,
$notIn: Op.notIn,
$is: Op.is,
$like: Op.like,
$notLike: Op.notLike,
$iLike: Op.iLike,
$notILike: Op.notILike,
$regexp: Op.regexp,
$notRegexp: Op.notRegexp,
$iRegexp: Op.iRegexp,
$notIRegexp: Op.notIRegexp,
$between: Op.between,
$notBetween: Op.notBetween,
$overlap: Op.overlap,
$contains: Op.contains,
$contained: Op.contained,
$adjacent: Op.adjacent,
$strictLeft: Op.strictLeft,
$strictRight: Op.strictRight,
$noExtendRight: Op.noExtendRight,
$noExtendLeft: Op.noExtendLeft,
$and: Op.and,
$or: Op.or,
$any: Op.any,
$all: Op.all,
$values: Op.values,
$col: Op.col
};
const sequelize = new Sequelize('token', 'root', 'user78', {
dialect: 'mysql',
operatorsAliases
//默认host和port
// host: "127.0.0.1",
// port: 3306,
});
sequelize.query("SELECT * FROM user").then(myTableRows => {
console.log(myTableRows)
})