Skip to main content

数据库设计

后端API项目使用MongoDB作为主数据库,Redis作为缓存层。

MongoDB模型设计

用户模型

import mongoose, { Document, Schema } from 'mongoose';

export interface IUser extends Document {
username: string;
email: string;
password: string;
avatar?: string;
role: 'admin' | 'user';
isActive: boolean;
createdAt: Date;
updatedAt: Date;
}

const UserSchema = new Schema<IUser>({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3,
maxlength: 30,
},
email: {
type: String,
required: true,
unique: true,
lowercase: true,
},
password: {
type: String,
required: true,
minlength: 6,
},
avatar: {
type: String,
default: null,
},
role: {
type: String,
enum: ['admin', 'user'],
default: 'user',
},
isActive: {
type: Boolean,
default: true,
},
}, {
timestamps: true,
});

// 索引
UserSchema.index({ email: 1 });
UserSchema.index({ username: 1 });

// 方法
UserSchema.methods.toJSON = function() {
const user = this.toObject();
delete user.password;
return user;
};

export const User = mongoose.model<IUser>('User', UserSchema);

文章模型

import mongoose, { Document, Schema } from 'mongoose';

export interface IArticle extends Document {
title: string;
content: string;
author: mongoose.Types.ObjectId;
tags: string[];
status: 'draft' | 'published' | 'archived';
views: number;
likes: mongoose.Types.ObjectId[];
createdAt: Date;
updatedAt: Date;
}

const ArticleSchema = new Schema<IArticle>({
title: {
type: String,
required: true,
trim: true,
maxlength: 200,
},
content: {
type: String,
required: true,
},
author: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
tags: [{
type: String,
trim: true,
}],
status: {
type: String,
enum: ['draft', 'published', 'archived'],
default: 'draft',
},
views: {
type: Number,
default: 0,
},
likes: [{
type: Schema.Types.ObjectId,
ref: 'User',
}],
}, {
timestamps: true,
});

// 索引
ArticleSchema.index({ author: 1, status: 1 });
ArticleSchema.index({ tags: 1 });
ArticleSchema.index({ createdAt: -1 });

export const Article = mongoose.model<IArticle>('Article', ArticleSchema);

Redis缓存策略

缓存配置

import Redis from 'ioredis';

const redis = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT || '6379'),
password: process.env.REDIS_PASSWORD,
retryDelayOnFailover: 100,
maxRetriesPerRequest: 3,
});

export default redis;

缓存使用示例

import redis from '../config/redis';

export class ArticleService {
async getArticleById(id: string) {
// 先从缓存获取
const cacheKey = `article:${id}`;
const cached = await redis.get(cacheKey);

if (cached) {
return JSON.parse(cached);
}

// 从数据库获取
const article = await Article.findById(id).populate('author', 'username avatar');

if (article) {
// 缓存1小时
await redis.setex(cacheKey, 3600, JSON.stringify(article));
}

return article;
}

async updateArticle(id: string, data: any) {
const article = await Article.findByIdAndUpdate(id, data, { new: true });

// 清除缓存
await redis.del(`article:${id}`);

return article;
}
}