跳至主内容区

查询缓存

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

你可以缓存通过 QueryBuilder 方法 getManygetOnegetRawManygetRawOnegetCount 选择的结果。

你也可以缓存通过 RepositoryEntityManagerfind*count* 方法选择的结果。

要启用缓存,你需要在数据源选项中显式开启:

{
type: "mysql",
host: "localhost",
username: "test",
...
cache: true
}

首次启用缓存时, 必须同步数据库结构(使用 CLI、迁移或 synchronize 数据源选项)。

然后在 QueryBuilder 中可为任意查询启用缓存:

const users = await dataSource
.createQueryBuilder(User, "user")
.where("user.isAdmin = :isAdmin", { isAdmin: true })
.cache(true)
.getMany()

等效的 Repository 查询:

const users = await dataSource.getRepository(User).find({
where: { isAdmin: true },
cache: true,
})

这将执行查询获取所有管理员用户并缓存结果。 下次执行相同代码时,会从缓存中获取管理员用户。 默认缓存有效期为 1000 ms(即 1 秒)。 这意味着查询构建器代码执行 1 秒后缓存将失效。 实践中,如果用户在 3 秒内打开用户页面 150 次,此期间只会执行三次查询。 在 1 秒缓存窗口期内新增的用户将不会被返回。

可通过 QueryBuilder 手动修改缓存时间:

const users = await dataSource
.createQueryBuilder(User, "user")
.where("user.isAdmin = :isAdmin", { isAdmin: true })
.cache(60000) // 1 minute
.getMany()

或通过 Repository 修改:

const users = await dataSource.getRepository(User).find({
where: { isAdmin: true },
cache: 60000,
})

或在数据源选项中全局设置:

{
type: "mysql",
host: "localhost",
username: "test",
...
cache: {
duration: 30000 // 30 seconds
}
}

此外,可以通过 QueryBuilder 设置 "缓存 ID":

const users = await dataSource
.createQueryBuilder(User, "user")
.where("user.isAdmin = :isAdmin", { isAdmin: true })
.cache("users_admins", 25000)
.getMany()

或使用 Repository 设置:

const users = await dataSource.getRepository(User).find({
where: { isAdmin: true },
cache: {
id: "users_admins",
milliseconds: 25000,
},
})

这使你能精细控制缓存, 例如在新增用户时清除缓存:

await dataSource.queryResultCache.remove(["users_admins"])

默认情况下,TypeORM 使用名为 query-result-cache 的独立表存储所有查询和结果。 表名可配置,通过在 tableName 属性指定不同值即可修改:

{
type: "mysql",
host: "localhost",
username: "test",
...
cache: {
type: "database",
tableName: "configurable-table-query-result-cache"
}
}

若在单一数据库表中存储缓存效率不高, 可将缓存类型改为 "redis" 或 "ioredis",TypeORM 会将缓存记录存储在 Redis 中:

{
type: "mysql",
host: "localhost",
username: "test",
...
cache: {
type: "redis",
options: {
socket: {
host: "localhost",
port: 6379
}
}
}
}

"options" 可以是 node_redis 特定配置ioredis 特定配置,具体取决于使用类型。

如需通过 IORedis 的集群功能连接 Redis 集群,可如下操作:

{
type: "mysql",
host: "localhost",
username: "test",
cache: {
type: "ioredis/cluster",
options: {
startupNodes: [
{
host: 'localhost',
port: 7000,
},
{
host: 'localhost',
port: 7001,
},
{
host: 'localhost',
port: 7002,
}
],
options: {
scaleReads: 'all',
clusterRetryStrategy: function (times) { return null },
redisOptions: {
maxRetriesPerRequest: 1
}
}
}
}
}

注意:你仍可将 options 作为 IORedis 集群构造函数的第一个参数。

{
...
cache: {
type: "ioredis/cluster",
options: [
{
host: 'localhost',
port: 7000,
},
{
host: 'localhost',
port: 7001,
},
{
host: 'localhost',
port: 7002,
}
]
},
...
}

如果内置缓存提供者无法满足需求, 可通过 provider 工厂函数指定自定义缓存提供者,该函数需返回实现 QueryResultCache 接口的新对象:

class CustomQueryResultCache implements QueryResultCache {
constructor(private dataSource: DataSource) {}
...
}
{
...
cache: {
provider(dataSource) {
return new CustomQueryResultCache(dataSource);
}
}
}

若希望在缓存出错时忽略错误并让查询透传到数据库,可使用 ignoreErrors 选项:

{
type: "mysql",
host: "localhost",
username: "test",
...
cache: {
type: "redis",
options: {
socket: {
host: "localhost",
port: 6379
}
},
ignoreErrors: true
}
}

可使用 typeorm cache:clear 命令清除缓存中的所有内容。