跳转到主要内容

查询缓存

您可以缓存由这些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: {
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: {
host: "localhost",
port: 6379
},
ignoreErrors: true
}
}

您可以使用 typeorm cache:clear 清除缓存中存储的所有内容。