每个索引对象可以设置的值:
name:索引名称,默认模型名称+字段
fields: Array,索引字段
unique:唯一索引,默认false
增加索引的好处就是让数据库查询数据的时候变得更快。
模型实例对象
模型实例对象的概念很好理解,模型对象的作用是操作某张数据表,模型实例对象的作用是操作这张数据表中的数据。
一个模型类对应一个表,一个模型实例对象就是一条对应的表记录,通过操作这个对象来关联操作对应的表中的数据,操作模型类就是操作表,操作模型类对象就是操作该表中的某条记录。
模型类——表
模型实例——记录
注意在数据库中,我们通常会把记录称为数据,也会把数据称为记录,概念是一样的。
创建模型实例对象
public static build(options: Object): Model | Model[]
options:一个对象,对应的就是表中的字段(模型中定义的属性),需要注意的是对该对象的操作不会立即反应到实际的数据库中,需要通过后续的操作进行同步
/**
* 模型类 -> 表
* 模型创建出来的对象 -> 表中某条记录
*/
// let Kimoo = new UserModel(); //创建了一个User的记录
let Kimoo = UserModel.build({ //和上面的new是一样的
// 字段对应的值
username: 'Kimoo',
age: 30,
gender: '男'
});
// 通过new或者build出来的对象不会立即同步到数据库中,需要使用后续的一些方法来同步
await Kimoo.save();
模型实例对象CRUD操作
模型实例对象.get(key: String):获取某个属性(字段)的值。
模型对象.set(key: String, value: any):设置某个属性(字段)的值。
模型对象.save():验证该实例,如果通过验证,则持久化到数据库中。
模型对象.update(updates: Object):updates:要更新的字段,调用该方法等同于调用.set()然后.save()。
模型对象.destroy():销毁该实例(假删除或真删除)。
// 创建数据模型实例对象 c4az6
// let c4az6 = UserModel.build({
// username: 'c4az6',
// age: 20,
// gender: '男'
// })
// 获取属性
/* console.log(`
username: ${c4az6.get('username')}
age: ${c4az6.get('age')}
gender: ${c4az6.get('gender')}
`); */
// 设置属性
// let res = c4az6.set('age', 21);
// console.log(res.dataValues);
// 通过save方法同步数据到数据库中
// await c4az6.save();
// 更新字段数据
let res = await UserModel.findById(17);
console.log(res.dataValues);
res.update({username: 'Alex'});
let res2 = await UserModel.findById(18);
res2.update({username: 'Elon', age: 40});
console.log(res2.dataValues);
// 销毁记录
res2.destroy();
除了通过模型创建出来的实例对单条数据进行操作,也可以通过模型类对整个对应的表进行操作。
模型.findById(id: Number | String | Buffer):根据主键搜索单条记录,注意是根据主键。
findById这个API在6.x的版本中已经被替换为findByPk了
模型.findOne(options: Object):根据条件搜索一条记录 options.where:搜索条件 Op操作。
模型.findOrCreate(options: Object):搜索特定记录或创建它(如果没有对应记录)options.where:搜索条件。
模型.findAll(findOptions: Object):在数据库中搜索多个记录,返回所有数据。
findOptions.where:搜索条件
findOptions.limit:记录条数限制
findOptions.offset:记录偏移
findOptions.order:记录排序方式
模型.findAndCountAll(findOptions: Object):与findAll类似,但是返回值包含 count 属性,返回数据与总计数。
// 数据模型实例对象查询相关操作
// findById
// let user = await UserModel.findById(17);
// console.log(user.dataValues);
// findOne 返回一个对象
// let res = await UserModel.findOne({
// where: {
// id: 17
// }
// })
// console.log(res.dataValues);
// 搜索或创建特定记录,如果不存在则创建,返回数组
// let res = await UserModel.findOrCreate({
// where: {
// id: 30,
// username: 'test'
// }
// })
// console.log(res[0].dataValues);
// 搜索多个记录,返回数据和总记录数, 返回数组
// 搜索年龄大于30的所有记录,这种对象嵌套对象的写法真恶心,一旦条件变多代码可读性会非常差
// let res = await UserModel.findAll({
// where: {
// age: {
// [Op.gt]: 30
// }
// }
// })
// console.log(res.length);
// res.map(item=>{console.log(item.dataValues)});
// 与findAll一样,但是在返回所有数据的基础上添加了count统计总记录数的字段, 返回数组
let res = await UserModel.findAndCountAll()
console.log(res.count)
res.rows.map(item=>{console.log(item.dataValues)});
过滤查询(Sequelize.Op)
// 过滤查询
// let res = await UserModel.findAll({
// where: {
// // 单条件过滤
// // username: 'Alex',
// // 多条件 要么年龄大于30,要么性别为女
// [Sequelize.Op.or]: [
// {
// age: {
// [Sequelize.Op.gt]: 30
// }
// },
// {
// gender: '女'
// }
// ]
// }
// })
// res.map(item=>{console.log(item.dataValues)});
// limit 限制记录查询
// let res = await UserModel.findAll({
// limit: 5
// });
// for(let i=0; i
// console.log(res[i].dataValues);
// }
// 分页查询 limit配合offset一起使用
// let res = await UserModel.findAll({
// limit: 5,
// offset: 5
// });
// console.log(res);
// res.some(item=>console.log(item.dataValues))
// 排序查询
// 年龄按照降序规则来排序
// let res = await UserModel.findAll({
// order: [['age', 'desc']]
// });
// res.forEach(item=>{console.log(item.dataValues)});
// 返回总记录数
// let res = await UserModel.count();
// console.log(res);
// 返回2条记录数和总记录数
// let res = await UserModel.findAndCountAll({
// limit: 2
// });
// console.log(res.count);
// res.rows.forEach(item=>{console.log(item.dataValues)});
// 计算gender字段为男的年龄总和
// let res = await UserModel.sum('age', {
// where: {
// gender: '男'
// }
// });
// console.log(res);
关联查询
1.首先给关联的字段定义外键关系
references: {
model: 关联的外键表,如User
key: 关联的外键表的字段,如id
}
在调用hasOne或hasMany等方法的时候,通过第二个参数设置对象:{foreignKey: 当前关联表的字段,如uid}
在查询中使用 include 去设置关联的外键表模型,如:include: [MessageModel]
// 关联查询
// 注意:创建模型的前提是你已经有建好了这张表
const MessageModel = sequelize.define('message', {
id: {
type: Sequelize.INTEGER(10),
primaryKey: true,
allowNull: true,
autoIncrement: true
},
uid: { // 关联其他表的字段,把当前字段定义为外键
type: Sequelize.INTEGER(10),
defaultValue: 0,
references: {
model: UserModel,
key: 'id'
}
},
content: {
type: Sequelize.STRING(255),
allowNull: true,
defaultValue: ''
}
}, {
timestamps: false,
freezeTableName: true, // 冻结表名称
tableName: 'message'
})
// Object.assign(data, {
// id: message.get('id'),
// uid: message.get('uid'),
// username: user.get('username'),
// age: user.get('age'),
// gender: user.get('gender'),
// content: message.get('content')
// });
// console.log(data);
// MessageModel属于UserModel模型对象
// MessageModel.belongsTo(UserModel, {
// // 关联外键
// foreignKey: 'uid'
// });
// let data2 = await MessageModel.findById(1, {
// // 设置查询出来的数据包含UserModel数据
// include: [UserModel]
// });
// // console.log(data2);
// console.log(`
// 留言id:${data2.get('id')}
// 留言人名称:${data2.User.username}
// 留言内容:${data2.get('content')}
// `);
// 关联查询与预加载
// 首先给关联的字段定义外键关系
// UserModel包含MessageModel对象,hasMany表示包含多个
UserModel.hasMany(MessageModel, {
foreignKey: 'uid'
});
// 在查询中使用include去设置关联的外键表模型,如:include:[MessageModel]
let data3 = await UserModel.findById(5, {
include: [MessageModel]
});
data3.messages.map(item => console.log(item.dataValues));