基于现有@nestjs/graphql配置,如何利用Redis缓存Resolver返回的大量数据?
用Redis缓存NestJS GraphQL Resolver的响应结果
我来一步步帮你实现用Redis缓存那个返回大量数据的getRates查询结果,基于你现有的代码和配置:
1. 安装必要依赖
首先得安装NestJS缓存模块和Redis存储适配器:
npm install @nestjs/cache-manager cache-manager cache-manager-redis-store # 或者用yarn yarn add @nestjs/cache-manager cache-manager cache-manager-redis-store
2. 配置全局CacheModule(使用Redis作为存储)
在你的AppModule里导入并配置CacheModule,把Redis设置为缓存存储介质,同时设为全局模块方便所有Resolver使用:
import { Module } from '@nestjs/common'; import { CacheModule } from '@nestjs/cache-manager'; import { redisStore } from 'cache-manager-redis-store'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { GraphQLModule } from '@nestjs/graphql'; import { graphQLConfig } from './your-graphql-config-path'; // 替换成你的GraphQL配置路径 @Module({ imports: [ ConfigModule.forRoot(), // 配置Redis缓存模块 CacheModule.registerAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: async (configService: ConfigService) => ({ store: await redisStore({ // 从配置文件读取Redis连接信息,根据你的实际配置调整 url: configService.get<string>('REDIS_URL'), // 如果没有用URL的话,可以单独配置host/port/password: // host: configService.get<string>('REDIS_HOST'), // port: configService.get<number>('REDIS_PORT'), // password: configService.get<string>('REDIS_PASSWORD'), ttl: 60, // 默认缓存过期时间(秒),可以根据需求调整 }), }), isGlobal: true, // 设为全局模块,避免在每个Resolver模块重复导入 }), // 导入你已有的GraphQL配置 GraphQLModule.forRootAsync(graphQLConfig), // 其他业务模块... ], }) export class AppModule {}
3. 给Resolver方法添加缓存装饰器
在你的getRates查询方法上使用@Cacheable装饰器,指定缓存key的生成规则和过期时间(可选,会覆盖全局TTL):
import { Query, Args, Resolver } from '@nestjs/graphql'; import { Cacheable } from '@nestjs/cache-manager'; import { ConvertRateType } from './your-type-path'; // 替换成你的类型路径 import { GetConvertRatesInput } from './your-input-path'; // 替换成你的输入类型路径 import { RatesService } from './rates.service'; @Resolver() export class RatesResolver { constructor(private readonly _ratesService: RatesService) {} @Query(() => [ConvertRateType]) @Cacheable({ // 根据请求参数生成唯一缓存key,确保不同输入参数对应不同缓存 key: (context) => { const input = context.args.input; // 这里根据你的GetConvertRatesInput结构拼接key,比如包含基础货币、目标货币、日期等 return `rates:${input.baseCurrency}:${input.targetCurrencies.join(',')}:${input.date}`; }, ttl: 300, // 单独设置这个查询的缓存过期时间(5分钟),可选 }) async getRates( @Args('input') input: GetConvertRatesInput, ): Promise<ConvertRateType[]> { const rates = await this._ratesService.getRates(input); return rates; } }
4. 可选:手动清除缓存(当数据更新时)
如果你的汇率数据会定期更新,需要清除旧缓存来返回最新数据,可以在RatesService里注入CacheManager来手动删除缓存:
import { Injectable, Inject } from '@nestjs/common'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; @Injectable() export class RatesService { constructor( @Inject(CACHE_MANAGER) private readonly cacheManager: Cache, // 其他依赖... ) {} async updateRates() { // 执行更新汇率数据的逻辑... // 清除特定缓存key(根据实际参数生成) await this.cacheManager.del('rates:USD:EUR,GBP:2024-05-20'); // 如果需要批量清除所有汇率缓存(生产环境建议用扫描而非keys命令) // const keys = await this.cacheManager.store.keys('rates:*'); // await Promise.all(keys.map(key => this.cacheManager.del(key))); } }
这样配置后,当第一次调用getRates查询时,NestJS会自动把查询结果存入Redis,后续相同参数的查询会直接从Redis返回缓存数据,直到缓存过期或者被手动清除。
内容的提问来源于stack exchange,提问作者Denys Rybkin
相关产品推荐
相关产品推荐

