# SequelizeQueryBuilder 使用
SequelizeQueryBuilder 使用文档
SequelizeQueryBuilder 是一个用于构建 Sequelize 查询的辅助类。它提供了一系列方法来构建查询条件、排序、分组、限制和选择字段等操作。以下是 SequelizeQueryBuilder 类的详细说明和使用示例。
# 例子
let builder = new sequelizeQueryBuilder()
let queryObj = builder
.select('author_id', 'video.aweme_id', 'video.title', 'video.cover', 'video.create_time', 'video.content_url',
'video.duration', 'video.digg_count', 'video.comment_count', 'video.forward_count', 'video.order_count') // 如果是查询连表里的字段,需要在字段前面写别名, 不写别名是查询当前表字段, 特殊查询使用raw方法
.where('platform_id', _.toInteger(query.platform_id))
.where('author_id', _.toInteger(query.author_id))
.when(query.product_id, queryBuilder => {
queryBuilder.where('product_id', query.product_id)
})
.where('type', CONST_ACTIVITY.JOIN_DETAIL_TYPE_VIDEO)
.join({
fromModel: this.compassModel.PlatformJoinDetail,
fromField: 'join_id',
toModel: this.compassModel.AuthorVideo,
toField: 'aweme_id',
as: 'video',
whereClosure: queryBuilder => {
queryBuilder.where('author_id', _.toInteger(query.author_id))
}// 连表的额外条件
})//连表
.when(query.order_key, queryBuilder => {
queryBuilder.orderBy(builder.raw('video.' + query.order_key), query.order_value ?? 'DESC')
})// 给连表的字段排序
.build()
queryObj.isPagination = true
this.pagination({params: query, origin_data: queryObj})
let data = await this.compassModel.PlatformJoinDetail.findAndCountAll(queryObj)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
let pageQueryBuilder = new sequelizeQueryBuilder()
let queryObj = pageQueryBuilder
.select('type', 'service_rate', 'commission_rate', 'exclusive_duration', 'commission_effect_end_time',
'id', 'product_id', 'activity_id', 'promotion_url', 'status', 'institution_account_id')
.where('admin_id', 'eq', query.admin_id)
.when(query?.query_type == 'product_id' && query?.q, (queryBuilder) => {
queryBuilder.where('product_id',query.q)
})
.when(query?.query_type == 'product_name' && query?.q, (queryBuilder) => {
queryBuilder.join({
fromModel: this.xpinModel.XpinInstitutionActivityGoods,
fromField: 'product_id',
toModel: this.compassModel.Product,
toField: 'product_id',
as: 'product'
}).join({
fromModel: this.xpinModel.XpinInstitutionActivityGoods,
fromField: 'id',
toModel: this.xpinModel.XpinInstitutionActivityGoodsExtension,
toField: 'id',
as: 'ext'
})
})
.when(query?.query_type == 'product_name' && query?.q, (queryBuilder) => {
query.q = `%${query.q}%`
queryBuilder.whereRaw(`(product.title like :q or ext.title like :q)`)
})
.when(query.shop_name, (pageQueryBuilder) => {
pageQueryBuilder.where('shop_name', 'like', '%'+query.shop_name+'%')
})
.when(query.status, (pageQueryBuilder) => {
pageQueryBuilder.where('status', 'eq', parseInt(query.status))
})
.when(query.is_new, (pageQueryBuilder) =>{
pageQueryBuilder.where('is_new', 'eq', parseInt(query.is_new))
})
.when(query.activity_id, (pageQueryBuilder) =>{
pageQueryBuilder.where('activity_id', 'eq', query.activity_id)
})
.when(query.commission_effect_end_time, (pageQueryBuilder) =>{
pageQueryBuilder.whereBetween('commission_effect_end_time',
this.helper.getExpireTimestamp({
expire: query.commission_effect_end_time,
is_all: query.is_all_expire ? true : false
}))
})
.when(query.type, (pageQueryBuilder) =>{
pageQueryBuilder.where('type', 'eq', query.type)
})
.when(query.exclusive_duration !== "" && query.exclusive_duration !== undefined, (pageQueryBuilder) =>{
if (query.exclusive_duration == 1){
pageQueryBuilder.where('exclusive_duration', '>', 0)
}else {
pageQueryBuilder.where('exclusive_duration', 0)
}
})
.when(query.plan_status, (pageQueryBuilder) =>{
switch (parseInt(query.plan_status)){
case 1: // 合作中
pageQueryBuilder.where('audit_status', 'eq', CONST_INST_ACTIVITY_GOODS.AUDIT_STATUS_PASS)
break
case 2: // 合作已终止
pageQueryBuilder.where('audit_status', 'eq', CONST_INST_ACTIVITY_GOODS.AUDIT_STATUS_STOP)
break
case 3: //合作已过期
pageQueryBuilder.where('audit_status', 'eq', CONST_INST_ACTIVITY_GOODS.AUDIT_STATUS_EXPIRE)
break
}
})
.when(!_.isEmpty(query.publish_status), (pageQueryBuilder) =>{ // 通过外接传入发布状态过滤数据
pageQueryBuilder.whereIn('publish_status', query.publish_status.map(i => parseInt(i)))
})
.when(query.order_key && query.order_value, queryBuilder => {
queryBuilder.orderBy(query.order_key, query.order_value == 'ascending' ? 'asc' : 'desc')
})
.bind(query)
.orderBy('published_at', 'desc')
.paginate({params: query}
// 分页查询
let data = await this.xpinModel.XpinInstitutionActivityGoods.findAndCountAll(queryObj)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# 构造函数
const builder = new SequelizeQueryBuilder();
使用 new
关键字创建一个新的 SequelizeQueryBuilder 实例。
# 查询条件
# where(...args)
添加一个查询条件,根据指定的字段、操作符和值进行匹配。
- 如果参数个数为 1,则表示使用回调函数的方式构建复杂的查询条件。
- 如果参数个数为 2,则表示添加一个基本的等值查询条件。
- 如果参数个数为 3,则表示添加一个指定操作符的查询条件。
- 查询的值也可以是原生sql。
示例:
builder.where('name', 'John');
builder.where('age', '>', 18);
builder.where((subQueryBuilder) => {
subQueryBuilder.where('age', '>', 18).where('name', 'John');
});
bilder.where('nickname', '=', builder.raw('name')
2
3
4
5
6
# orWhere(callback)
添加一个使用 OR 连接的复杂查询条件,可以通过回调函数的方式构建复杂的嵌套条件。
提示:orWhere里第一层的查询生成出来后,全部使用 or 连接,sql:( xxx or xxx ),如果需要嵌套 and 查询, 需要自己使用 where 闭包
示例:
builder.orWhere((subQueryBuilder) => {
subQueryBuilder.where('age', '>', 18).where('name', 'John');
});
2
3
# when(condition, callback)
添加一个满足前置条件的查询条件,通过回调函数的方式构建条件。
示例:
builder.when(!_.isEmpty(query),(subQueryBuilder) => {
subQueryBuilder.where('age', '>', 18).where('name', 'John');
});
2
3
# whereIn(field, values)
添加一个查询条件,检查指定字段的值是否在给定的值数组中。
示例:
builder.whereIn('id', [1, 2, 3]);
# whereNotIn(field, values)
添加一个查询条件,检查指定字段的值不在给定的值数组中。
示例:
builder.whereNotIn('id', [1, 2, 3]);
# whereBetween(field, values)
添加一个查询条件,检查指定字段的值是否在给定的范围内。
示例:
builder.whereBetween('age', [18, 30]);
# whereNotBetween(field, values)
添加一个查询条件,检查指定字段的值是否不在给定的范围内。
示例:
builder.whereNotBetween('age', [0, 18]);
# whereBetweenTimeStamps(field, values)
添加一个查询条件,检查指定字段的值是否在给定的时间戳(已适配秒级/毫秒级)范围内, 结束时间会自动加86400-1秒。
示例:
builder.whereBetweenTimeStamps('created_at', [1704211200, 1704211200]);
# whereNull(field)
添加一个查询条件,检查指定字段的值是否为 null。
示例:
builder.whereNull('email');
# whereNotNull(field)
添加一个查询条件,检查指定字段的值是否不为 null。
示例:
builder.whereNotNull('email');
# whereDate(field, date)
添加一个查询条件,检查指定字段的日期是否与给定的日期匹配。
示例:
builder.whereDate('createdAt', '2022-01-01');
# whereMonth(field, month)
添加一个查询条件,检查指定字段的月份是否与给定的月份匹配。
示例:
builder.whereMonth('createdAt', 3);
# whereYear(field, year)
添加一个查询条件,检查指定字段的年份是否与给定的年份匹配。
示例:
builder.whereYear('createdAt', 2022);
# whereTime(field, time)
添加一个查询条件,检查指定字段的时间是否与给定的时间匹配。
示例:
builder.whereTime('createdAt', '09:00:00');
# whereRaw(condition)
添加一个原始查询条件,使用原始的 SQL 条件语句。
示例:
builder.whereRaw('LENGTH(name) > 5');
# 排序和分组
# orderBy(field, direction)
指定结果集的排序方式。可以指定字段和排序方向('ASC' 或 'DESC')。
示例:
builder.orderBy('createdAt', 'DESC');
builder.orderBy(builder.raw('balance+point*2'), 'DESC');
2
# groupBy(field)
指定结果集的分组字段。
示例:
builder.groupBy('category').groupBy(builder.raw("max(id)"));
# 聚合函数和限制
# having(...args)
添加一个聚合函数的条件,根据指定的字段、操作符和值进行匹配。
- 如果参数个数为 1,则表示使用回调函数的方式构建复杂的查询条件。
- 如果参数个数为 2,则表示添加一个基本的等值查询条件。
- 如果参数个数为 3,则表示添加一个指定操作符的查询条件。
- 查询的值也可以是原生sql。
示例:
builder.having('name', 'John');
builder.having('age', '>', 18);
builder.having((subQueryBuilder) => {
subQueryBuilder.having('age', '>', 18).having('name', 'John');
});
bilder.having('nickname', '=', builder.raw('name')
2
3
4
5
6
# orHaving(callback)
添加一个使用 OR 连接的复杂查询条件,可以通过回调函数的方式构建复杂的嵌套条件。
提示:orHaving里第一层的查询生成出来后,全部使用 or 连接,sql:( xxx or xxx ),如果需要嵌套 and 查询, 需要自己使用 having 闭包
示例:
builder.orHaving((subQueryBuilder) => {
subQueryBuilder.having('age', '>', 18).having('name', 'John');
});
2
3
# havingRaw(condition)
添加一个聚合函数的条件,使用原始的 SQL 条件语句。
示例:
builder.havingRaw('LENGTH(name) > 5');
# limit(value)
指定查询结果的最大返回数量。
示例:
builder.limit(10);
# offset(value)
指定查询结果的偏移量,用于分页查询。
示例:
builder.offset(20);
# paginate({ params, maxLimit = 200, defaultLimit = 20 })
为查询构建器设置 limit 和 offset,实现分页查询,同时也会构建并返回最终的查询对象,也就是内部会调用build方法。
参数
maxLimit
- 最大限制,默认为200。超过这个值时使用这个值defaultLimit
- 默认限制,默认为20。如果没传limit
参数则使用这个值
实现:
- 获取
limit
参数的值,如果没有则使用defaultLimit
值 - 检查
limit
值是否超过maxLimit
,如果超过则使用maxLimit
值 - 计算offset值:
- 如果有
offset
参数,则直接使用 - 如果有
page
参数,则取(page - 1) * limit
- 否则默认为0
- 如果有
- 将
limitValue
和offsetValue
设为函数的属性
示例:
builder.paginate({ params: query });
# 结果集选择
# select(...fields)
指定查询结果中要选择的字段。
查询主表不需要带别名(除非是raw查询), 查询连表需要带别名
示例:
// 基本查询
builder.select('name', 'age');
// 连表后,获取连表内的字段,以及使用原始语句,假设主表model是User,连了profile表,且别名也是profile
// 查询内容是, 姓名,年级,个性签名,身份证,手机号(地区+手机号)
builder.select('name', 'age', 'profile.bio', builder.raw('profile.idcard as idcard,concat(User.area_code,User.phone) as phone'))
2
3
4
5
6
# selectRaw(value)
指定查询结果中要执行的原始sql。
示例:
// 基本查询
builder.selectRaw('count(1) as cnt');
2
# 参数绑定和事务
# bind(values)
绑定查询参数,用于预防 SQL 注入攻击。
提示:不支持多次调用。
示例:
builder.bind({name:'John'});
# bindTransaction(transaction)
绑定事务对象,用于在SQL操作中使用事务。
示例:
builder.bindTransaction(transaction);
# 连表
# join({options})
- fromModel - 源模型
- fromField - 源模型的外键
- toModel - 目标模型
- toField - 目标模型的外键
- as - 别名
- whereClosure - 一个回调执行子查询构建器来设置where条件 跟where参数二选一
- where - 一个where条件(优先级高于whereClosure) 跟whereClosure参数二选一
连表查询
连表后如果需要在外面做字段查询或者条件检索,需要带上别名
示例:
builder.join({
fromModel: User,
fromField: 'id',
toModel: Post,
toField: 'userId',
as: 'posts',
whereClosure: (subQueryBuilder) => {
subQueryBuilder.where('title', 'like', '%hello%');
},
where: new sequelizeQueryBuilder().where('title', 'like', '%hello%').build().where
})
2
3
4
5
6
7
8
9
10
11
# leftJoin({options})
执行左连接。参数同 join() ,只是执行左连接而不是内连接。
示例:
builder.leftJoin({
fromModel: User,
fromField: 'id',
toModel: Post,
toField: 'userId',
as: 'posts'
})
2
3
4
5
6
7
# 构建查询对象
# build()
构建并返回最终的查询对象。
示例:
const query = builder.build();
console.log(query);
2
← 低代码文档