数据库设计
后端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;
}
}