CRUD(查询)
下面以模块test-vona为例,讲解 CRUD 中Select的用法
基本查询
模块test-vona中定义了 ModelPost,可以这样查询Post的数据
1. select
class ServicePost {
async select() {
return await this.scope.model.post.select();
}
}2. count
class ServicePost {
async count() {
return await this.scope.model.post.count();
}
}3. select and count
class ServicePost {
async selectAndCount() {
return await this.scope.model.post.selectAndCount();
}
}4. get
class ServicePost {
async get(id: TableIdentity) {
return await this.scope.model.post.get({ id });
}
}5. mget
class ServicePost {
async mget(ids: TableIdentity[]) {
return await this.scope.model.post.mget(ids);
}
}Select类型定义
async select<
T extends IModelSelectParams<TRecord>,
ModelJoins extends TypeModelsClassLikeGeneral | undefined,
>(
params?: T,
options?: IModelMethodOptions,
_modelJoins?: ModelJoins,
): Promise<TRecord[]>;- 举例:一个相对复杂的 select 查询:
class ServicePost {
async select() {
return await this.scope.model.post.select({
columns: ['id', 'title', 'userId'],
where: {
'id': { _gt_: 1 },
'testVonaUser.id': 1,
},
joins: [['innerJoin', 'testVonaUser', ['userId', 'testVonaUser.id']]],
offset: 0,
limit: 20,
orders: [['createdAt', 'desc']],
}, {
disableDeleted: false,
}, 'test-vona:user');
}
}Select参数:Options
| 名称 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| disableDeleted | boolean | false | 是否禁止软删除 |
| disableCreateTime | boolean | false | 是否禁止自动设置创建时间 |
| disableUpdateTime | boolean | false | 是否禁止自动设置更新时间 |
| disableCacheQuery | boolean | false | 是否禁用Cache Query |
| disableCacheEntity | boolean | false | 是否禁用Cache Entity |
| deleted | boolean | undefined | 可以显式设置deleted值 |
Select参数:Params
| 名称 | 描述 |
|---|---|
| distinct | 是否启用distinct |
| columns | 需要查询的字段列表 |
| where | 条件语句 |
| joins | 关联表 |
| orders | 排序 |
| limit | 可用于分页查询 |
| offset | 可用于分页查询 |
| include | 静态关系 |
| with | 动态关系 |
orders
是数组类型,可以指定多个 orders:
async select() {
return await this.scope.model.post.select({
orders: [
['createdAt', 'desc'],
['title', 'asc'],
],
});
}joins
可以通过joins关联多个数据表
async select() {
return await this.scope.model.post.select({
joins: [
['innerJoin', 'testVonaUser', ['userId', 'testVonaUser.id']],
['leftJoin', 'testVonaPostContent', ['id', 'testVonaPostContent.postId']],
],
});
}joins支持类型提示,如图所示:

那么,图中所示的数据表清单来自于哪里呢?
前面提到,可以在Model中定义多个Entity之间的关系,所以,系统自动从 Model 定义的关系中提取 Entity 对应的数据表。ModelPost的关系定义如下:
@Model({
relations: {
postContent: $relation.hasOne('test-vona:postContent', 'postId', { columns: ['id', 'content'] }),
user: $relation.belongsTo(() => ModelPost, () => ModelUser, 'userId', { autoload: true, columns: ['id', 'name'] }),
},
})
class ModelPost {}在一个大型的业务系统中,Model 可能并不会定义所有的关系。那么,也可以通过参数_modelJoins指定需要关联的 Models,系统从这些 Models 中提取对应的数据表
比如,模块test-vona中定义了 modelorder。那么,我们可以这样使用joins:

也可以指定多个 Models:

where:普通操作符
1. 基本用法
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
title: { _includes_: 'ai' },
stars: { _gt_: 20 },
},
});
}
}class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
stars: {
_gt_: 20,
_lt_: 50,
},
},
});
}
}2. 普通操作符清单
| 名称 | 说明 |
|---|---|
| _eq_ | |
| _notEq_ | |
| _gt_ | |
| _gte_ | |
| _lt_ | |
| _lte_ | |
| _in_ | |
| _notIn_ | |
| _is_ | value值为null或undefined |
| _isNot_ | value值为null或undefined |
| _between_ | |
| _notBetween_ | |
| _startsWith_ | |
| _endsWith_ | |
| _includes_ | |
| _startsWithI_ | 非敏感的字符串操作符 |
| _endsWithI_ | 非敏感的字符串操作符 |
| _includesI_ | 非敏感的字符串操作符 |
| _ref_ | value为标识符 |
| _skip_ | 如果value等于_skip,则忽略当前条件 |
3. 用法举例
- Array
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
title: {
_in_: ['ai', 'web'],
},
},
});
}
}select * from "testVonaPost" where ("title" in ('ai', 'web'))
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
title: ['ai', 'web'],
},
});
}
}select * from "testVonaPost" where "title" in ('ai', 'web')
- 判空
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
title: {
_is_: null,
},
},
});
}
}select * from "testVonaPost" where ("title" is null)
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
title: null,
},
});
}
}select * from "testVonaPost" where "title" is null
- _ref_
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
title: {
_ref_: 'title',
},
},
});
}
}select * from "testVonaPost" where ("title" = "title")
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
title: {
_ref_: 'testVonaPost.title',
},
},
});
}
}select * from "testVonaPost" where ("title" = "testVonaPost"."title")
- _skip_
class ServicePost {
async select() {
const where = {
title: { _includes_: 'ai' },
stars: { _gt_: 20 },
};
return await this.scope.model.post.select({
where: {
...where,
stars: '_skip_' as const,
},
});
}
}select * from "testVonaPost" where ("title" like '%ai%')
where:连接操作符
1. 基本用法
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
_or_: {
title: { _includes_: 'ai' },
stars: { _gt_: 20 },
},
},
});
}
}select * from "testVonaPost" where ((("title" like '%ai%')) or (("stars" > 20)))
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
stars: {
_or_: {
_lt_: 20,
_gt_: 50,
},
},
},
});
}
}select * from "testVonaPost" where ((("stars" < 20) or ("stars" > 50)))
2. 连接操作符清单
| 名称 | 说明 |
|---|---|
| _and_ | |
| _or_ | |
| _not_ | |
| _exists_ | |
| _notExists_ |
3. 用法举例
- _not_
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
_not_: {
title: { _includes_: 'ai' },
stars: { _gt_: 20 },
},
},
});
}
}select * from "testVonaPost" where not (("title" like '%ai%') and ("stars" > 20))
- _exists_
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
_exists_: function (builder: Knex.QueryBuilder) {
builder
.select('*')
.from('testVonaPostContent')
.where('postId', this.scope.model.post.ref('testVonaPost.id'));
} as any,
},
});
}
}select * from "testVonaPost" where exists (select * from "testVonaPostContent" where "postId" = "testVonaPost"."id")
where:raw
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: this.scope.model.post.raw('?? > ?', ['stars', 20]) as any,
});
}
}select * from "testVonaPost" where "stars" > 20
where:ref
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
title: {
'_eq_': this.scope.model.post.ref('title') as any,
}
},
});
}
}select * from "testVonaPost" where ("title" = "title")
class ServicePost {
async select() {
return await this.scope.model.post.select({
where: {
title: {
'_eq_': this.scope.model.post.ref('testVonaPost.title') as any,
}
},
});
}
}select * from "testVonaPost" where ("title" = "testVonaPost"."title")