Want to use Nestjs with other Redis command

jel*_*lly 3 backend redis node.js nestjs

I try to implement nestjs backend and redis as caching. I can do it according to the official document https://docs.nestjs.com/techniques/caching#in-memory-cache.

I use the package cache-manager-redis-store and the code in app.module.ts is as shown below.

import { Module, CacheModule } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import * as redisStore from 'cache-manager-redis-store';
import * as Joi from 'joi';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    CacheModule.registerAsync({
      imports: [
        ConfigModule.forRoot({
          validationSchema: Joi.object({
            REDIS_HOST: Joi.string().default('localhost'),
            REDIS_PORT: Joi.number().default(6379),
            REDIS_PASSWORD: Joi.string(),
          }),
        }),
      ],
      useFactory: async (configService: ConfigService) => ({
        store: redisStore,
        auth_pass: configService.get('REDIS_PASSWORD'),
        host: configService.get('REDIS_HOST'),
        port: configService.get('REDIS_PORT'),
        ttl: 0,
      }),
      inject: [ConfigService],
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)

With this setting, I can use get and set as expected but I want to use other redis command such as hget and zadd. Unfortunately, I cannot find the guide anywhere.

I think there must be a way since cache-manager-redis-store package said that it just passing the configuration to the underlying node_redis package. And node-redis package can use those fancy redis commands.

Would be appreciated if you have solutions.

jel*_*lly 6

感谢 Micael Levi 和 Hamidreza Vakilian 的帮助。我做了更多研究并找到了我的解决方案,因此我将与其他有同样问题的人分享。

它似乎cache-manager-redis-store只允许正常的redis操作,如果你想使用更多,你必须cacheManager.store.getClient()按照Micael的建议进行访问。

Cache接口没有getClient但是RedisCache有!问题是包RedisCache内的接口cache-manager-redis-store不向外部导出这些接口。

解决此问题的最简单方法是创建redis.interface.ts自己的名称或任何名称。

import { Cache, Store } from 'cache-manager';
import { RedisClient } from 'redis';

export interface RedisCache extends Cache {
  store: RedisStore;
}

export interface RedisStore extends Store {
  name: 'redis';
  getClient: () => RedisClient;
  isCacheableValue: (value: any) => boolean;
}
Run Code Online (Sandbox Code Playgroud)

现在你可以CacheRedisCache接口替换。

用法如下。

import {
  CACHE_MANAGER,
  Inject,
  Injectable,
} from '@nestjs/common';
import { RedisClient } from 'redis';
import { RedisCache } from './interface/redis.interface';

@Injectable()
export class RedisService {
  private redisClient: RedisClient;
  constructor(@Inject(CACHE_MANAGER) private cacheManager: RedisCache) {
    this.redisClient = this.cacheManager.store.getClient();
  }

  hgetall() {
    this.redisClient.hgetall('mykey', (err, reply) => {
      console.log(reply);
    })
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这些redisClient命令不返回值,因此您必须使用回调来获取值。

正如你所看到的,答案是在回调结构中,我更喜欢awaitasync所以我做了更多的工作。

import {
  BadRequestException,
  CACHE_MANAGER,
  Inject,
  Injectable,
} from '@nestjs/common';
import { RedisClient } from 'redis';
import { RedisCache } from './interface/redis.interface';

@Injectable()
export class RedisService {
  private redisClient: RedisClient;
  constructor(@Inject(CACHE_MANAGER) private cacheManager: RedisCache) {
    this.redisClient = this.cacheManager.store.getClient();
  }

  async hgetall(key: string): Promise<{ [key: string]: string }> {
    return new Promise<{ [key: string]: string }>((resolve, reject) => {
      this.redisClient.hgetall(key, (err, reply) => {
        if (err) {
          console.error(err);
          throw new BadRequestException();
        }
        resolve(reply);
      });
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

通过使用promise,我可以像函数返回一样得到答案。用法如下。

import { Injectable } from '@nestjs/common';
import { RedisService } from './redis.service';

@Injectable()
export class UserService {
  constructor(private readonly redisService: RedisService) {}

  async getUserInfo(): Promise<{ [key: string]: string }> {
    const userInfo = await this.redisService.hgetall('mykey');
    return userInfo;
  }
}
Run Code Online (Sandbox Code Playgroud)