Skip to content

Nest 中使用 Redis

本文重点解释 ioredis 的安装与使用,以及如何在 Nest 中使用 ioredis。

ioredis

我这里使用的是 yml 配置文件

安装 ioredis 类库

ts
pnpm install ioredis --save

创建一个全局模块 redis

  • 代码
ts
nest g resource redis

修改这个模块

  • (1) 删除控制器 redis.controller.ts

  • (2) 修改 redis.module.ts

ts
import { Module, Global } from "@nestjs/common";
import { RedisService } from "./redis.service";

@Global()
@Module({
  controllers: [],
  providers: [RedisService],
  exports: [RedisService],
})
export class RedisModule {}
  • (3) 修改 redis.service.ts(env 配置)
ts
import { Inject, Injectable } from "@nestjs/common";
import { Redis } from "ioredis";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class RedisService {
  // 定义
  private readonly redis: Redis;
  constructor(private readonly configServiceAll: ConfigService) {
    this.redis = new Redis({
      host: this.configServiceAll.get("REDIS_HOST"), // 主机
      port: this.configServiceAll.get("REDIS_PORT"), // 端口
      password: this.configServiceAll.get("REDIS_PASSWORD"), // 密码
      db: this.configServiceAll.get("REDIS_DB"), // 数据库
      family: 4, // IPV4||IPV6
    });
  }

  // Redis获取所有的keys
  async getAllKeys(args: string = "*"): Promise<string[]> {
    return await this.redis.keys(args);
  }

  // Redis 获取单个key的值
  async get(key: string): Promise<string | null> {
    return await this.redis.get(key);
  }

  // 删除
  async delkey(key: string): Promise<number> {
    return await this.redis.del(key);
  }

  // 字符串方法 data 里面 有key ,value,ttl(可选)
  async setstr(data: any, ttl?: number) {
    const ttlresult = await this.redis.ttl(data.key); // 获取到剩余的时间 -2 就代表不存在

    if (ttlresult == -2) {
      const expiration: any = ttl || this.configServiceAll.get("REDIS_TTL"); // 单位秒
      await this.redis.set(data.key, data.value, "EX", expiration);
      const key = await this.getAllKeys(data.key); // 获取到key
      const value = await this.get(key[0]); // 获取到对应的value
      const result = {};
      result[key[0]] = value;
      return result;
    } else {
      const expiration = ttl || ttlresult;
      await this.redis.set(data.key, data.value, "EX", expiration);
      const key = await this.getAllKeys(data.key); // 获取到key
      const value = await this.get(key[0]); // 获取到对应的value
      const result = {};
      result[key[0]] = value;
      return result;
    }
  }

  // 字符串获取
  async getstr(key: string): Promise<string | null> {
    return await this.redis.get(key);
  }

  // -------------哈希只能一级。要是嵌套太多 就转成字符串 --------------------

  async sethash(key: string, data: any, ttl?: number) {
    const ttlresult = await this.redis.ttl(key); // 获取到剩余的时间 -2 就代表不存在
    if (ttlresult == -2) {
      // 新来的
      const expiration: any = ttl || this.configServiceAll.get("REDIS_TTL"); // 单位秒
      for (let attr in data) {
        await this.redis.hset(key, attr, data[attr]);
      }
      await this.redis.expire(key, expiration); // 设置过期时间
      return this.gethash(key); // 返回结果
    } else {
      // 以前就存过
      for (let attr in data) {
        await this.redis.hset(key, attr, data[attr]);
      }
      const expiration: any = ttl || ttlresult; // 单位秒
      await this.redis.expire(key, expiration);
      return this.gethash(key);
    }
  }

  async gethash(key: string): Promise<any> {
    return await this.redis.hgetall(key);
  }

  // ---------------- 列表设置 ------------
  async setlist(key: string, data: any[], ttl?: number) {
    const ttlresult = await this.redis.ttl(key); // 获取到剩余的时间 -2 就代表不存在

    if (ttlresult == -2) {
      // 新来的
      const expiration: any = ttl || this.configServiceAll.get("REDIS_TTL"); // 单位秒
      for (let i = 0; i < data.length; i++) {
        await this.redis.rpush(key, data[i]);
      }
      await this.redis.expire(key, expiration); // 设置过期时间
      return this.getlist(key); // 返回结果
    } else {
      // 以前就有
      for (let i = 0; i < data.length; i++) {
        await this.redis.rpush(key, data[i]);
      }
      const expiration: any = ttl || ttlresult; // 单位秒
      await this.redis.expire(key, expiration); // 设置过期时间
      return this.getlist(key); // 返回结果
    }
  }

  //-------------列表获取----------
  async getlist(key: string): Promise<any> {
    return await this.redis.lrange(key, 0, -1);
  }
}
  • (4) 修改 redis.service.ts(yml 配置)
ts
import { Inject, Injectable } from "@nestjs/common";
import { Redis } from "ioredis";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class RedisService {
  // 定义
  private readonly redis: Redis;
  constructor(private readonly configServiceAll: ConfigService) {
    this.redis = new Redis({
      host: this.configServiceAll.get("redis").host, // 主机
      port: this.configServiceAll.get("redis").port, // 端口
      password: this.configServiceAll.get("redis").password, // 密码
      db: this.configServiceAll.get("redis").db, // 数据库
      family: 4, // IPV4||IPV6
    });
  }

  // Redis获取所有的keys
  async getAllKeys(args: string = "*"): Promise<string[]> {
    return await this.redis.keys(args);
  }

  // Redis 获取单个key的值
  async get(key: string): Promise<string | null> {
    return await this.redis.get(key);
  }

  // 删除
  async delkey(key: string): Promise<number> {
    return await this.redis.del(key);
  }

  // 字符串方法
  async setstr(data: any) {
    const ttl = await this.redis.ttl(data.key); // 获取到剩余的时间 -2 就代表不存在
    console.log(ttl);
    if (ttl == -2) {
      const expiration = this.configServiceAll.get("redis").ttl; // 单位秒
      await this.redis.set(data.key, data.value, "EX", expiration);
      const key = await this.getAllKeys(data.key); // 获取到key
      const value = await this.get(key[0]); // 获取到对应的value
      const result = {};
      result[key[0]] = value;
      return result;
    } else {
      await this.redis.set(data.key, data.value, "EX", ttl);
      const key = await this.getAllKeys(data.key); // 获取到key
      const value = await this.get(key[0]); // 获取到对应的value
      const result = {};
      result[key[0]] = value;
      return result;
    }
  }

  // 字符串获取
  async getstr(key: string): Promise<string | null> {
    return await this.redis.get(key);
  }

  // -------------哈希只能一级。要是嵌套太多 就转成字符串 --------------------
  async sethash(key: string, data: any) {
    const ttl = await this.redis.ttl(key); // 获取到剩余的时间 -2 就代表不存在
    console.log(ttl);
    if (ttl == -2) {
      // 新来的
      const expiration = this.configServiceAll.get("redis").ttl; // 单位秒
      for (let attr in data) {
        await this.redis.hset(key, attr, data[attr]);
      }
      await this.redis.expire(key, expiration); // 设置过期时间
      return this.gethash(key); // 返回结果
    } else {
      // 以前就存过
      for (let attr in data) {
        await this.redis.hset(key, attr, data[attr]);
      }
      await this.redis.expire(key, ttl);
      return this.gethash(key);
    }
  }

  async gethash(key: string): Promise<any> {
    return await this.redis.hgetall(key);
  }

  // ---------------- 列表设置 ------------
  async setlist(key: string, data: any[]) {
    const ttl = await this.redis.ttl(key); // 获取到剩余的时间 -2 就代表不存在
    console.log(ttl);
    if (ttl == -2) {
      // 新来的
      const expiration = this.configServiceAll.get("redis").ttl; // 单位秒
      for (let i = 0; i < data.length; i++) {
        await this.redis.rpush(key, data[i]);
      }
      await this.redis.expire(key, expiration); // 设置过期时间
      return this.getlist(key); // 返回结果
    } else {
      // 以前就有
      for (let i = 0; i < data.length; i++) {
        await this.redis.rpush(key, data[i]);
      }
      await this.redis.expire(key, ttl); // 设置过期时间
      return this.getlist(key); // 返回结果
    }
  }

  //-------------列表获取----------
  async getlist(key: string): Promise<any> {
    return await this.redis.lrange(key, 0, -1);
  }
}

使用

控制器

ts
import { Controller, Post, Body } from "@nestjs/common";
import { UserService } from "./user.service";

@Controller("user")
export class UserController {
  constructor(private readonly userService: UserService) {}

  // 查询所有的key
  @Post("getallkeys")
  async getallkeys() {
    const result = await this.userService.getAllKeys();
    console.log(result);
    return {
      data: result,
    };
  }

  // 查看匹配的keys
  @Post("getcheckkeys")
  async getcheckkeys(@Body() body: any) {
    const params = body.value;
    console.log(params);
    const result = await this.userService.getcheckkeys(params);
    console.log(result);
    return {
      data: result,
    };
  }

  // 删除指定的key
  @Post("delkey")
  async delkey(@Body() body: any) {
    const params = body.value;
    console.log(params);
    const result = await this.userService.delkey(params);
    let message = "";
    if (result == 1) {
      message = "删除成功";
    }
    return {
      data: {
        message,
      },
    };
  }

  // ------------- 字符串-------------------
  // 设置字符串
  @Post("setstr")
  async setstr(@Body() body: any) {
    const value = body.value;
    const key = body.key;
    const result = await this.userService.setstr({ key, value });
    console.log(result);
    return {
      data: result,
    };
  }

  // 获取字符串
  @Post("getstr")
  async getstr(@Body() body: any) {
    const key = body.key;
    const result = await this.userService.getstr(key);
    console.log(result);
    return {
      data: result,
    };
  }

  // -------------对象Hash开始---------------
  @Post("sethash")
  async sethash(@Body() body: any) {
    const hashresult = { key: "hash1", value: { ...body } };
    const result = await this.userService.sethash(
      hashresult.key,
      hashresult.value
    );
    console.log(result);
    return {
      data: result,
    };
  }

  // --------获取hash------
  @Post("gethash")
  async gethash(@Body() body: any) {
    const key = body.key;
    const result = await this.userService.getallhash(key);
    console.log(result);
    return {
      data: result,
    };
  }

  // -------------列表---------------
  @Post("setlist")
  async setlist(@Body() body: any) {
    console.log(body);
    const listresult = { key: "list1", value: [...body.list1] };
    const result = await this.userService.setlist(
      listresult.key,
      listresult.value
    );
    console.log(result);
    return {
      data: result,
    };
  }

  // --------列表获取------------
  @Post("getlist")
  async getlist(@Body() body: any) {
    const key = body.key;
    const result = await this.userService.getlist(key);
    console.log(result);
    return {
      data: result,
    };
  }
}

services

ts
import { Inject, Injectable } from "@nestjs/common";
import { RedisService } from "../redis/redis.service";
import { ConfigService } from "@nestjs/config";
import { JwtServiceAll } from "../jwt/jwt.service";
// 数据库
import { PrismadbService } from "../prisma/prisma.service";
@Injectable()
export class UserService {
  // 注入配置文件
  @Inject()
  private readonly configService: ConfigService;
  // 注入Redis
  @Inject()
  private readonly redisService: RedisService;
  // 注入jwt
  @Inject()
  private readonly jwtService: JwtServiceAll;
  // 注入数据库
  @Inject()
  private readonly prismadbService: PrismadbService;
  // 获取所有的keys
  async getAllKeys() {
    const result = await this.redisService.getAllKeys();
    return result;
  }

  // 获取所有匹配的keys
  async getcheckkeys(data: string) {
    const result = await this.redisService.getAllKeys(data);
    return result;
  }

  // 删除指定的key
  async delkey(data: string) {
    const result = await this.redisService.delkey(data);
    return result;
  }

  // 字符串方法设置
  async setstr(data: Object) {
    const result: any = await this.redisService.setstr(data);
    return result;
  }

  // 字符串方法获取
  async getstr(data: string) {
    const result: any = await this.redisService.getstr(data);
    return result;
  }

  /*------------------设置hash------------------------*/

  async sethash(key: string, data: Object) {
    const result: any = await this.redisService.sethash(key, data);
    return result;
  }

  // 获取所有的hash
  async getallhash(key: string) {
    const result: any = await this.redisService.gethash(key);
    return result;
  }

  // ---------列表-------------------
  async setlist(key: string, data: any[]) {
    const result: any = await this.redisService.setlist(key, data);
    return result;
  }

  async getlist(key: string) {
    const result: any = await this.redisService.getlist(key);
    return result;
  }
}