# MongoDB 索引创建指南

本项目使用 MongoDB 作为数据库，为了确保良好的查询性能，需要手动创建以下索引。

## 连接到 MongoDB

```bash
# 连接到 MongoDB
mongo mongodb://localhost:27017/jimeng-api

# 或者使用 MongoDB Compass 等图形工具
```

## 需要创建的索引

### 1. 生成任务表 (jimeng_free_generation_tasks)

```javascript
// 基础索引
db.jimeng_free_generation_tasks.createIndex({ "task_id": 1 }, { unique: true });
db.jimeng_free_generation_tasks.createIndex({ "server_id": 1 });
db.jimeng_free_generation_tasks.createIndex({ "status": 1 });
db.jimeng_free_generation_tasks.createIndex({ "created_at": 1 });
db.jimeng_free_generation_tasks.createIndex({ "next_poll_at": 1 });

// 复合索引 - 用于轮询查询优化
db.jimeng_free_generation_tasks.createIndex({ 
    "server_id": 1, 
    "status": 1, 
    "next_poll_at": 1 
});

// 复合索引 - 用于服务器负载查询
db.jimeng_free_generation_tasks.createIndex({ 
    "server_id": 1, 
    "created_at": 1 
});
```

### 2. 生成结果表 (jimeng_free_generation_results)

```javascript
// 基础索引
db.jimeng_free_generation_results.createIndex({ "task_id": 1 }, { unique: true });
db.jimeng_free_generation_results.createIndex({ "server_id": 1 });
db.jimeng_free_generation_results.createIndex({ "created_at": 1 });
db.jimeng_free_generation_results.createIndex({ "is_read": 1 });
db.jimeng_free_generation_results.createIndex({ "first_read_at": 1 });

// TTL索引 - 自动清理过期记录
db.jimeng_free_generation_results.createIndex({ 
    "expires_at": 1 
}, { 
    expireAfterSeconds: 0 
});

// 复合索引
db.jimeng_free_generation_results.createIndex({ 
    "server_id": 1, 
    "created_at": 1 
});

// 复合索引 - 用于查询已读取/未读取的结果
db.jimeng_free_generation_results.createIndex({ 
    "is_read": 1, 
    "created_at": 1 
});
```

### 3. 服务器心跳表 (jimeng_servers)

```javascript
// 基础索引
db.jimeng_servers.createIndex({ "server_id": 1 }, { unique: true });
db.jimeng_servers.createIndex({ "last_heartbeat": 1 });

// 复合索引 - 用于查询在线服务器
db.jimeng_servers.createIndex({ 
    "is_active": 1, 
    "last_heartbeat": 1 
});
```

## 一键执行脚本

将以下内容保存为 `create_indexes.js` 文件，然后执行：

```javascript
// create_indexes.js
print("开始创建 jimeng-free-api 数据库索引...");

// 生成任务表索引
db = db.getSiblingDB('jimeng-api');

print("创建生成任务表索引...");
db.jimeng_free_generation_tasks.createIndex({ "task_id": 1 }, { unique: true });
db.jimeng_free_generation_tasks.createIndex({ "server_id": 1 });
db.jimeng_free_generation_tasks.createIndex({ "status": 1 });
db.jimeng_free_generation_tasks.createIndex({ "created_at": 1 });
db.jimeng_free_generation_tasks.createIndex({ "next_poll_at": 1 });
db.jimeng_free_generation_tasks.createIndex({ "server_id": 1, "status": 1, "next_poll_at": 1 });
db.jimeng_free_generation_tasks.createIndex({ "server_id": 1, "created_at": 1 });

print("创建生成结果表索引...");
db.jimeng_free_generation_results.createIndex({ "task_id": 1 }, { unique: true });
db.jimeng_free_generation_results.createIndex({ "server_id": 1 });
db.jimeng_free_generation_results.createIndex({ "created_at": 1 });
db.jimeng_free_generation_results.createIndex({ "is_read": 1 });
db.jimeng_free_generation_results.createIndex({ "first_read_at": 1 });
db.jimeng_free_generation_results.createIndex({ "expires_at": 1 }, { expireAfterSeconds: 0 });
db.jimeng_free_generation_results.createIndex({ "server_id": 1, "created_at": 1 });
db.jimeng_free_generation_results.createIndex({ "is_read": 1, "created_at": 1 });

print("创建服务器心跳表索引...");
db.jimeng_servers.createIndex({ "server_id": 1 }, { unique: true });
db.jimeng_servers.createIndex({ "last_heartbeat": 1 });
db.jimeng_servers.createIndex({ "is_active": 1, "last_heartbeat": 1 });

print("所有索引创建完成！");
```

执行命令：
```bash
mongo mongodb://localhost:27017/jimeng-api create_indexes.js
```

## 验证索引

创建完成后，可以验证索引是否正确创建：

```javascript
// 查看所有集合的索引
db.jimeng_free_generation_tasks.getIndexes();
db.jimeng_free_generation_results.getIndexes();
db.jimeng_servers.getIndexes();
```

## 性能说明

- **唯一索引**：确保 task_id 和 server_id 的唯一性
- **复合索引**：优化多字段查询，特别是轮询任务时的复杂查询
- **TTL 索引**：自动清理过期的结果记录，释放存储空间
- **时间索引**：加速基于时间的查询和排序

这些索引的创建顺序不影响功能，但建议按照文档顺序执行以确保最佳性能。

## 注意事项

1. **数据库名称**：请根据实际使用的数据库名称调整脚本中的 `jimeng-api`
2. **连接地址**：请根据实际的 MongoDB 连接地址调整命令
3. **权限要求**：执行索引创建需要数据库的写权限
4. **生产环境**：在生产环境中创建索引可能需要考虑对性能的影响，建议在低峰期执行