## 实例化 > 实例化可以传入一个数组,或单个 object 配置。只有 1 个数据库时,默认是主库; > 多于 1 个数据库服务时,自动以第 1 个为主库,其他的从库,故实例化时`注意顺序`。 ```javascript let Mysqli = require('mysqli') //传入json let conn = new Mysqli({ host: '', // IP/域名 post: 3306, //端口, 默认 3306 user: '', //用户名 passwd: '', //密码 charset: '', // 数据库编码,默认 utf8 【可选】 db: '' // 可指定数据库,也可以不指定 【可选】 }) // 传入数组 let conn = new Mysqli([ { host: 'host1', // IP/域名 ... }, ... ]) ``` ## 实例 API ### 静态方法 escape(val) > 可以对 sql 的各种类型的值进行安全转义。 ### emit([slave], [db]) * slave [可选]是否"从库", 默认为 false, * db [可选]要连接的数据库名, 默认为空 > 返回一个 db 实例, 这个方法是必须要的, 所有的 sql 操作,都要先实例一个 db 对象。 ```javascript let db = conn.emit(false, 'test') db .tableList() .then(list => { log(list) }) .catch(err => { log(err) }) ``` ## DB API > 是指直接对 db 进行操作的接口。如果没有特别说明,以下所有的方法, 返回的都是一个 Promise 对象。 ### query(sql) * sql sql 语句, [必传] > 直接执行 sql 语句, 用于在内置的 API 不满足需求的情况下, 可以自己手写 sql 执行。 ```javascript db.query('select * from `student` limit 10').then(result => { log(result) }) // 前面没有指定数据库时, 也可以在这里写上 db.query('select * from `test`.`student` limit 10').then(result => { log(result) }) ``` ### drop(db) * db [可选] 要删除 db 名, 不传则删除当前连接的数据库 > 删除当前或指定数据库。 ```javascript db.drop() // 也可以删除指定的数据库 db.drop('foo') ``` ### dbList() > 返回当前账号权限下的所有的数据名(数组) ```javascript db.dbList().then(list => { log(list) }) ``` ### tableList() > 返回当前连接的数据库下的所有的表名(数组) ```javascript db.tableList().then(list => { log(list) }) ``` ### dbCreate(name, options) * name [必传], 数据库名字 * options , [必传], 数据库的配置 * charset 默认 utf8 > 创建新的数据库 ```javascript db.dbCreate('foo', { charset: 'utf8mb4' }) // 默认是utf8 ``` ### tableCreate(name, columns ,options) * name [必传], 表名字 * columns , [必传], 表字段的配置 * name 字段名, 区分大小写, 建议全小写+下划线 * type 字段类型, 不区分大小写 * primary 是否主键(有且只能有 1 个主键) * inc 是否自增(只允许主键设置,且为整型时才可设置) * notnull 是否允许非空 * index 是否设为索引 * unique 是否为 唯一索引 * default 设置默认值 * update 是否自动更新(只有 datetime & timestamp 可以设) * options , [必传], 表的配置 * charset 默认 utf8 * engine 默认 InnoDB > 创建新的数据表 ```javascript db.tableCreate('student', [ { name: 'id', type: 'int(5)', primary: true, inc: true }, { name: 'name', type: 'varchar(64)', index: true }, { name: 'age', type: 'int(3)' }, { name: 'sex', type: 'tinyint(1)', index: true }, ... ] {charset: 'utf8mb4'}) // 默认是utf8 ``` ### table(name) * name [必传], 数据表名字 > 选择指定表。 返回一个表操作的 API 实例 ```javascript let table = db.table('student') // ``` ## TABLE API > 是指直接对 table 进行操作的接口。 ### leftJoin(tables) * tables 左联, 可以联多个表 * table 表名 * on 左联的条件 ```javascript db.table('student') .leftJoin([ { table: 'classroom', on: 'student.classroom = classroom.id' }, ... ]) ``` ### rightJoin(tables) > 参考 leftJoin() ### join(tables) > 参考 leftJoin() ### filter(options) * options > 查询过滤, 这个方法是增删改查中使用率最高的。 也是 Mysqli 模块的核心方法之一。也是参数最复杂的方法, 一条查询里, 只能出现一次 filter, 多次调用, 会覆盖之前的条件. > options 里有几个特殊的关键字 > > * $and (逻辑"且") > * $or (逻辑"或") > * $like 模糊查询 > * $sql 以某个 sql 语句的结果作为查询条件 > * $in 包含 > * $between 在某某值和某某值之间 > * $lt 小于 > * $lte 小于等于 > * $gt 大于 > * $gte 大于等于 > * $eq 等于 ```javascript db .table('student') .filter({ id: 1234 }) // 最基本的过滤查询, 即条件为 找"id=1234"的 .filter({ name: { $like: '李%' } }) // 模糊查询, 找所有"李姓的学生" // 现有的API不满足时, 可以自己写sql条件, 更复杂自己根据需求写即可 .filter({ name: { $sql: 'IS NULL' } }) .filter({ id: { $in: [11, 13, 29] } }) // 查询id在给定的这几个值的所有学生 .filter({ age: { $between: [15, 17] } }) // 查询年龄在 15~17岁的所有学生 .filter({ age: { $lt: 16 } }) // 查询年龄小于16岁的所有学生 .filter({ age: { $lt: 16, $gt: 13 } }) // 查询年龄小于16岁且大于13岁的所有学生 // ***** 以下是多条件的示例 ********* // 查询所有姓李的,年龄15岁以上, 且为男生(假设 男生是1,女生是2) .filter({ name: { $like: '李%' }, age: { $gt: 15 }, sex: 1 }) // **** 从上面的示例可以看出,多个字段时, 自动为"AND" 查询 **** // **** 所以下面该 $and 和 $or 出场了 **** // 查询所有 姓李的, 或 年龄在15岁以上的 .filter({ $or: [{ name: { $like: '李%' } }, { age: { $gt: 15 } }] }) // 姓李的 或 年龄15岁以上且为男生的 .filter({ $or: [{ name: { $like: '李%' } }, { age: { $gt: 15 }, sex: 1 }] }) // 姓李的或15岁以上的, 且必须是男生的 .filter({ $and: [ { $or: [{ name: { $like: '李%' } }, { age: { $gt: 15 } }] }, { sex: 1 } ] }) // filter基本上满足了你日常绝大部分的查询需求, 如果还有没满足的, 可以自己写sql语句. ``` ### sort(keys) * keys > 对结果集排序 ```javascript db .table('student') .sort({ age: -1 }) // -1为逆序, 1为正序 // 先排年龄(逆序), 再排学号(正序) .sort({ age: -1, id: 1 }) ``` ### skip(num) * num > 跳过指定条数, 可用于分页。 ```javascript db.table('student').skip(10) // 跳过前9条, 即从第10条结果开始返回 ``` ### limit(num) * num > 限制返回的结果总数, 做分页时, 配合 skip 方法使用。 ```javascript db.table('student').limit(10) // 限制只返回10条记录 ``` ### slice(start, end) * start * end > 截取指定范围的结果集, 这是 skip & limit 结合体。 ```javascript db .table('student') .slice(11, 20) // 限制只返回10条记录 // 等价于 .skip(11) .limit(10) ``` ### withFields(fields) * fields [可选], 不传则返回所有的字段 > 指定要返回的字段 ```javascript db.table('student').withFields(['id', 'name', 'sex']) // 只取 学号,姓名,性别3个字段返回 ``` ### getAll([ids]) * ids [可选],返回指定 id 的结果集; 不传则返回所有结果集。(仅当没有调用过 filter 的情况下,本参数才有效) > 返回符合条件的所有记录, 这个方法是 查询必须要调用的方法之一, 上面 .filter, .sort 等方法, 只是组件条件, 并不会返回结果, 只有调用了 getAll/get 之后, 才会返回结果集。 > `这里有一个地方要注意的, 传入的参数ids, 即意味着, 该数据表里, 必须有一个字段为"id", 否则会出错, 没有id的表, 查询时请使用 .filter过滤。` ```javascript db .table('student') .withFields(['id', 'name', 'sex']) .getAll() .then(list => { log(list) }) // 以下是查询学号为 11,13,28的学生 db .table('student') .withFields(['id', 'name', 'sex']) .getAll([11, 13, 28]) .then(list => { log(list) }) // 等价于 db .table('student') .withFields(['id', 'name', 'sex']) .filter({ id: { $in: [11, 13, 28] } }) .getAll() .then(list => { log(list) }) // 在getAll()方法里传参数, 只是一种快捷的filter, // 没有"id"字段的表, 请使用 .filter()方法来查询 ``` ### get(id) * id [可选], 传入单个 ID。 > 该方法是对 getAll 的补充, 它最终是调用 getAll 来实现, 目的在于返回 单个结果集(不是数组)。 ```javascript // 以下是查询学号为 11的学生 db .table('student') .withFields(['id', 'name', 'sex']) .getAll(11) .then(doc => { log(doc) }) // 等价于 db .table('student') .withFields(['id', 'name', 'sex']) .filter({ id: 11 }) .get() .then(doc => { log(doc) }) ``` ### count() > 该方法同样是对 getAll 的补充, 它最终是调用 getAll 来实现, 返回结果集的总数。 ```javascript // 返回所有姓李的学生的总数 db .table('student') .filter({name: {$like: '李%'}}) .count() .then(total => { log(total) }) ``` ### insert(doc) * doc 要插入的记录 > 用于插入单条记录。如果有自增ID的话, 将返回刚插入的记录的自增ID。 ```javascript db .table('student') .insert({ name: '张三', age: 18, sex: 1, ... }) .then(lastId => { log(lastId) // 如果表结构里没有自增ID, 则这个返回值永远为0 }) ``` ### update(doc) * doc 要插入的记录 > 用于更新指定条件的记录, 返回成功修改的总数 ```javascript // 将张三的年龄改为 17岁 db .table('student') .filter({name: '张三'}) .update({ age: 17 }) .then(successNum => { log(successNum) }) ``` ### remove() > 删除记录。返回成功删除的总数。 ```javascript // 将姓名为空的记录全删除了。 db .table('student') .filter({name: {$sql: 'IS NULL'}}) .remove() .then(successNum => { log(successNum) }) ``` ### drop() > 删除当前数据表, 属于`危险操作`哦。 成功返回true。 ```javascript // 将学生表给删除了 db .table('student') .drop() .then(result => { log(result) }) ``` ### renameTo(name) > 重命名表。成功返回true。 ```javascript db .table('student') .renameTo('student_bac') .then(result => { log(result) }) ``` ### indexList() > 返回当前表的索引列表. ```javascript db .table('student') .indexList() .then(list => { log(list) // { // name, // column, // unique, // cardinality, // collation, // } }) ``` ### indexDrop(name) * name 索引名 > 删除当前表的指定索引. 成功返回true。 ```javascript // 将学生表给删除了 db .table('student') .indexDrop('name_idx') .then(result => { log(result) }) ``` ### indexDrop(name, options) * name 索引名 * options 索引的配置 - field 该索引绑定的字段 - unique 是否是唯一索引 > 给当前表创建索引. 成功返回true。 ```javascript // 将学生表给删除了 db .table('student') .indexCreate('name_idx', {field: 'name'}) .then(result => { log(result) }) ```