docs(manual): 添加 Gomog 完整 API 和操作符文档

- 新增聚合管道参考文档 (AGGREGATION_PIPELINE.md),涵盖数据过滤、转换、分组等阶段
- 新增 HTTP API 参考文档 (HTTP_API.md),包含数据库管理、文档操作、查询等功能接口
- 新增查询操作符参考文档 (QUERY_OPERATORS.md),提供完整的比较、逻辑、数组等操作符说明
- 包含详细的 API 端点、请求参数、响应格式及使用示例
- 提供最佳实践和性能优化建议
- 覆盖从基础 CRUD 操作到复杂聚合管道的完整功能说明
This commit is contained in:
kingecg 2026-03-14 19:46:35 +08:00
parent e44ee72382
commit 7b38ec9877
8 changed files with 4803 additions and 0 deletions

View File

@ -0,0 +1,807 @@
# Gomog 聚合管道参考文档
**版本**: v1.0.0-alpha
**最后更新**: 2026-03-14
---
## 📖 目录
1. [概述](#概述)
2. [数据过滤阶段](#数据过滤阶段)
3. [数据转换阶段](#数据转换阶段)
4. [数据分组阶段](#数据分组阶段)
5. [关联查询阶段](#关联查询阶段)
6. [递归查找阶段](#递归查找阶段)
7. [性能优化阶段](#性能优化阶段)
8. [使用示例](#使用示例)
---
## 概述
### 什么是聚合管道?
聚合管道是一种强大的数据处理机制,允许你将多个操作组合成一个流水线。每个阶段接收前一个阶段的输出作为输入,并产生新的输出传递给下一个阶段。
### 基本语法
```json
{
"pipeline": [
{"$stage1": {...}},
{"$stage2": {...}},
{"$stage3": {...}}
]
}
```
### 执行流程
```
输入 → [$match] → [$group] → [$sort] → [$limit] → 输出
↓ ↓ ↓ ↓
过滤 分组 排序 限制
```
---
## 数据过滤阶段
### $match
过滤文档,只传递符合条件的文档到下一阶段。
**语法**:
```json
{"$match": {"<field>": {"<operator>": <value>}}}
```
**示例**:
```json
{
"$match": {
"status": "active",
"age": {"$gte": 18, "$lte": 65},
"score": {"$gt": 80}
}
}
```
**支持的查询操作符**:
- 比较:`$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`
- 逻辑:`$and`, `$or`, `$not`, `$nor`
- 元素:`$exists`, `$type`, `$size`
- 数组:`$all`, `$elemMatch`
- 正则:`$regex`
### $limit
限制通过的文档数量。
**语法**:
```json
{"$limit": <number>}
```
**示例**:
```json
{"$limit": 10}
```
### $skip
跳过指定数量的文档。
**语法**:
```json
{"$skip": <number>}
```
**示例**:
```json
{"$skip": 20}
```
### $sample
随机采样文档。
**语法**:
```json
{"$sample": {"size": <number>}}
```
**示例**:
```json
{"$sample": {"size": 5}}
```
### $bucket
将文档分组到桶中。
**语法**:
```json
{
"$bucket": {
"groupBy": "<expression>",
"boundaries": [<boundary1>, <boundary2>, ...],
"default": <literal>,
"output": {<output1>: {<expression1>}, ...}
}
}
```
**示例**:
```json
{
"$bucket": {
"groupBy": "$price",
"boundaries": [0, 100, 500, 1000],
"default": "Other",
"output": {
"count": {"$sum": 1},
"avgPrice": {"$avg": "$price"}
}
}
}
```
---
## 数据转换阶段
### $project
重塑文档结构(选择字段、添加计算字段等)。
**语法**:
```json
{
"$project": {
"<field1>": <expression>,
"<field2>": <expression>,
...
}
}
```
**示例**:
```json
{
"$project": {
"name": 1,
"email": 1,
"_id": 0,
"fullName": {"$concat": ["$firstName", " ", "$lastName"]},
"ageInMonths": {"$multiply": ["$age", 12]}
}
}
```
**支持的表达式操作符**:
- 算术:`$add`, `$subtract`, `$multiply`, `$divide`, `$pow`, `$sqrt`
- 字符串:`$concat`, `$substr`, `$trim`, `$split`, `$replaceAll`
- 比较:`$max`, `$min`, `cmp`
- 条件:`$cond`, `$ifNull`, `$switch`
- 类型转换:`$toString`, `$toInt`, `$toDouble`, `$toBool`
### $addFields / $set
添加新字段或修改现有字段。
**语法**:
```json
{
"$addFields": {
"<newField>": <expression>
}
}
```
**示例**:
```json
{
"$addFields": {
"total": {"$add": ["$price", "$tax"]},
"discountedPrice": {"$multiply": ["$price", 0.9]}
}
}
```
### $unset / $unset
移除字段。
**语法**:
```json
{"$unset": "<field>"}
// 或
{"$unset": ["<field1>", "<field2>", ...]}
```
**示例**:
```json
{"$unset": ["tempField", "internalData"]}
```
### $replaceRoot / $replaceWith
替换根文档。
**语法**:
```json
{"$replaceRoot": {"newRoot": <expression>}}
```
**示例**:
```json
{
"$replaceRoot": {"newRoot": "$user"}
}
```
---
## 数据分组阶段
### $group
按指定键分组并计算聚合值。
**语法**:
```json
{
"$group": {
"_id": <expression>,
"<field1>": {<accumulator1>},
"<field2>": {<accumulator2>},
...
}
}
```
**示例**:
```json
{
"$group": {
"_id": "$department",
"employeeCount": {"$sum": 1},
"avgSalary": {"$avg": "$salary"},
"maxSalary": {"$max": "$salary"},
"minSalary": {"$min": "$salary"},
"totalSalary": {"$sum": "$salary"}
}
}
```
**累加器操作符**:
- `$sum`: 求和
- `$avg`: 平均值
- `$min`: 最小值
- `$max`: 最大值
- `$push`: 推入数组
- `$addToSet`: 添加到集合(去重)
- `$first`: 第一个值
- `$last`: 最后一个值
- `$count`: 计数
### $sort
对文档进行排序。
**语法**:
```json
{"$sort": {"<field1>": <order>, "<field2>": <order>, ...}}
```
**示例**:
```json
{
"$sort": {
"createdAt": -1, // 降序
"name": 1 // 升序
}
}
```
### $sortByCount
按值分组并计数。
**语法**:
```json
{"$sortByCount": <expression>}
```
**示例**:
```json
{"$sortByCount": "$category"}
```
等价于:
```json
[
{"$group": {"_id": "$category", "count": {"$sum": 1}}},
{"$sort": {"count": -1}}
]
```
---
## 关联查询阶段
### $lookup
左外连接其他集合。
**语法 1** (基本形式):
```json
{
"$lookup": {
"from": "<collection>",
"localField": "<field>",
"foreignField": "<field>",
"as": "<outputField>"
}
}
```
**示例 1**:
```json
{
"$lookup": {
"from": "orders",
"localField": "_id",
"foreignField": "userId",
"as": "orders"
}
}
```
**语法 2** (高级形式,支持管道):
```json
{
"$lookup": {
"from": "<collection>",
"let": {<var1>: <expression>, ...},
"pipeline": [<stages>],
"as": "<outputField>"
}
}
```
**示例 2**:
```json
{
"$lookup": {
"from": "orders",
"let": {"userId": "$_id"},
"pipeline": [
{"$match": {"$expr": {"$eq": ["$userId", "$$userId"]}}},
{"$sort": {"createdAt": -1}},
{"$limit": 5}
],
"as": "recentOrders"
}
}
```
### $graphLookup
递归查找关联文档。
**语法**:
```json
{
"$graphLookup": {
"from": "<collection>",
"startWith": <expression>,
"connectFromField": "<field>",
"connectToField": "<field>",
"as": "<outputField>",
"maxDepth": <number>,
"depthField": "<string>",
"restrictSearchWithMatch": <document>
}
}
```
**示例**:
```json
{
"$graphLookup": {
"from": "orgs",
"startWith": "$parentId",
"connectFromField": "_id",
"connectToField": "parentId",
"as": "subOrgs",
"maxDepth": 5,
"depthField": "level"
}
}
```
---
## 性能优化阶段
### $facet
多面聚合(并行执行多个子管道)。
**语法**:
```json
{
"$facet": {
"<outputField1>": [<stages>],
"<outputField2>": [<stages>],
...
}
}
```
**示例**:
```json
{
"$facet": {
"products": [
{"$match": {"category": "electronics"}},
{"$limit": 10}
],
"categories": [
{"$groupBy": "category"},
{"$count": "count"}
],
"priceStats": [
{"$group": {
"_id": null,
"avgPrice": {"$avg": "$price"},
"maxPrice": {"$max": "$price"}
}}
]
}
}
```
### $indexStats
获取集合的索引统计信息。
**语法**:
```json
{"$indexStats": {}}
```
**示例**:
```json
{
"$facet": {
"data": [{"$match": {"status": "active"}}],
"indexes": [{"$indexStats": {}}]
}
}
```
---
## 窗口函数阶段
### $setWindowFields
为每个文档计算窗口函数。
**语法**:
```json
{
"$setWindowFields": {
"partitionBy": <expression>,
"sortBy": {<field>: <order>, ...},
"output": {
"<field>": {
"<windowOperator>": {},
"window": {
"documents": [<lower>, <upper>]
}
},
...
}
}
}
```
**示例**:
```json
{
"$setWindowFields": {
"partitionBy": "$region",
"sortBy": {"date": 1},
"output": {
"runningTotal": {
"$sum": "$amount",
"window": {"documents": ["unbounded", "current"]}
},
"movingAvg": {
"$avg": "$amount",
"window": {"documents": [-2, 0]}
},
"rank": {"$documentNumber": {}}
}
}
}
```
**支持的窗口操作符**:
- `$sum`: 累加和
- `$avg`: 移动平均
- `$min`: 窗口最小值
- `$max`: 窗口最大值
- `$first`: 窗口第一个值
- `$last`: 窗口最后一个值
- `$documentNumber`: 文档序号
- `$rank`: 排名
- `$denseRank`: 密集排名
- `$percentRank`: 百分比排名
- `$cumeDist`: 累积分布
- `$shift`: 偏移值
- `$fill`: 填充值
---
## 使用示例
### 电商订单分析
```json
{
"pipeline": [
{
"$match": {
"status": "completed",
"createdAt": {"$gte": ISODate("2024-01-01")}
}
},
{
"$lookup": {
"from": "customers",
"localField": "customerId",
"foreignField": "_id",
"as": "customer"
}
},
{
"$unwind": "$customer"
},
{
"$group": {
"_id": "$customer.region",
"totalRevenue": {"$sum": "$amount"},
"orderCount": {"$sum": 1},
"avgOrderValue": {"$avg": "$amount"},
"topCustomers": {
"$push": {
"name": "$customer.name",
"total": "$amount"
}
}
}
},
{
"$sort": {"totalRevenue": -1}
},
{
"$limit": 10
}
]
}
```
### 用户行为分析
```json
{
"pipeline": [
{
"$match": {
"eventType": "page_view",
"timestamp": {"$gte": ISODate("2024-01-01")}
}
},
{
"$setWindowFields": {
"partitionBy": "$userId",
"sortBy": {"timestamp": 1},
"output": {
"sessionNumber": {
"$documentNumber": {}
},
"timeOnPage": {
"$subtract": [
{"$shift": {"n": 1, "default": "$$NOW.timestamp"}},
"$timestamp"
]
}
}
}
},
{
"$group": {
"_id": "$userId",
"totalViews": {"$sum": 1},
"avgTimeOnPage": {"$avg": "$timeOnPage"},
"uniquePages": {"$addToSet": "$pageId"}
}
},
{
"$project": {
"_id": 0,
"userId": "$_id",
"totalViews": 1,
"avgTimeOnPage": 1,
"uniquePages": {"$size": "$uniquePages"}
}
}
]
}
```
### 社交网络分析
```json
{
"pipeline": [
{
"$match": {"_id": ObjectId("...")}
},
{
"$graphLookup": {
"from": "users",
"startWith": "$friends",
"connectFromField": "friends",
"connectToField": "_id",
"as": "network",
"maxDepth": 3,
"depthField": "degree"
}
},
{
"$unwind": "$network"
},
{
"$group": {
"_id": "$network.degree",
"people": {"$addToSet": "$network.name"}
}
},
{
"$project": {
"degree": "$_id",
"count": {"$size": "$people"},
"people": 1
}
},
{
"$sort": {"degree": 1}
}
]
}
```
### 财务报表生成
```json
{
"pipeline": [
{
"$facet": {
"revenue": [
{"$match": {"type": "income"}},
{"$group": {"_id": null, "total": {"$sum": "$amount"}}}
],
"expenses": [
{"$match": {"type": "expense"}},
{"$group": {"_id": null, "total": {"$sum": "$amount"}}}
],
"byCategory": [
{
"$group": {
"_id": "$category",
"total": {"$sum": "$amount"},
"count": {"$sum": 1}
}
},
{"$sort": {"total": -1}},
{"$limit": 10}
]
}
},
{
"$project": {
"netProfit": {
"$subtract": [
{"$arrayElemAt": ["$revenue.total", 0]},
{"$arrayElemAt": ["$expenses.total", 0]}
]
},
"topCategories": "$byCategory"
}
}
]
}
```
---
## 最佳实践
### 1. 尽早过滤
```json
// ✅ 推荐:先过滤再处理
{"$match": {...}},
{"$group": {...}},
{"$sort": {...}}
// ❌ 不推荐:先处理再过滤
{"$group": {...}},
{"$match": {...}}
```
### 2. 使用投影减少数据量
```json
{"$project": {"neededField": 1, "unneededField": 0}}
```
### 3. 合理使用索引
```json
// 确保 $match 阶段使用有索引的字段
{"$match": {"indexedField": value}}
```
### 4. 限制结果集大小
```json
// 总是使用 $limit 防止内存溢出
{"$limit": 1000}
```
### 5. 避免昂贵的操作
```json
// ❌ 避免在 $match 中使用 $where
{"$match": {"$where": "this.field > 100"}}
// ✅ 使用标准操作符
{"$match": {"field": {"$gt": 100}}}
```
---
## 性能调优
### explain 分析
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/aggregate \
-H "Content-Type: application/json" \
-d '{
"pipeline": [...],
"explain": true
}'
```
### 监控慢聚合
```yaml
log:
level: "debug"
slow_aggregation_threshold: "500ms"
```
---
**维护者**: Gomog Team
**许可证**: MIT

867
manual/HTTP_API.md Normal file
View File

@ -0,0 +1,867 @@
# Gomog HTTP API 参考文档
**版本**: v1.0.0-alpha
**最后更新**: 2026-03-14
**基础路径**: `/api/v1`
---
## 📖 目录
1. [概述](#概述)
2. [认证与授权](#认证与授权)
3. [数据库管理](#数据库管理)
4. [集合管理](#集合管理)
5. [文档操作](#文档操作)
6. [查询操作](#查询操作)
7. [聚合操作](#聚合操作)
8. [索引管理](#索引管理)
9. [错误处理](#错误处理)
10. [响应格式](#响应格式)
---
## 概述
### 协议
- **传输协议**: HTTP/1.1 或 HTTP/2
- **数据格式**: JSON
- **字符编码**: UTF-8
- **默认端口**: 8080
### 基础 URL
```
http://localhost:8080/api/v1/{database}/{collection}/{operation}
```
### URL 参数说明
| 参数 | 说明 | 示例 |
|------|------|------|
| `{database}` | 数据库名称 | `testdb` |
| `{collection}` | 集合名称 | `users` |
| `{operation}` | 操作类型 | `find`, `insert`, `update` 等 |
### HTTP 方法
| 方法 | 用途 |
|------|------|
| POST | 执行数据库操作(查询、插入、更新、删除等) |
| GET | 获取元数据信息 |
---
## 数据库管理
### 列出所有数据库
**端点**: `POST /api/v1/admin/listDatabases`
**请求**:
```bash
curl -X POST http://localhost:8080/api/v1/admin/listDatabases
```
**响应**:
```json
{
"ok": 1,
"databases": [
{"name": "testdb", "sizeOnDisk": 1024, "empty": false},
{"name": "prod", "sizeOnDisk": 2048, "empty": false}
],
"totalSize": 3072,
"totalSizeMb": 3
}
```
### 列出当前数据库的集合
**端点**: `POST /api/v1/{database}/listCollections`
**请求**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/listCollections
```
**响应**:
```json
{
"ok": 1,
"collections": [
{"name": "users", "type": "collection"},
{"name": "orders", "type": "collection"}
]
}
```
---
## 集合管理
### 创建集合
Gomog 会在首次插入数据时自动创建集合,无需手动创建。
### 删除集合
**端点**: `POST /api/v1/{database}/{collection}/drop`
**请求**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/drop
```
**响应**:
```json
{
"ok": 1,
"nIndexesWas": 1
}
```
### 重命名集合
**端点**: `POST /api/v1/{database}/{collection}/renameCollection`
**请求**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/renameCollection \
-H "Content-Type: application/json" \
-d '{"to": "members"}'
```
**响应**:
```json
{
"ok": 1
}
```
---
## 文档操作
### 插入文档
**端点**: `POST /api/v1/{database}/{collection}/insert`
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `documents` | array | ✅ | 要插入的文档数组 |
| `ordered` | boolean | ❌ | 是否按顺序插入(默认 true |
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/insert \
-H "Content-Type: application/json" \
-d '{
"documents": [
{
"name": "Alice",
"age": 30,
"email": "alice@example.com"
},
{
"name": "Bob",
"age": 25,
"email": "bob@example.com"
}
]
}'
```
**响应**:
```json
{
"ok": 1,
"n": 2,
"insertedIds": {
"0": "20240101120000.000000000",
"1": "20240101120001.000000000"
}
}
```
**错误响应**:
```json
{
"ok": 0,
"errmsg": "duplicate key error",
"code": 11000
}
```
---
## 查询操作
### 查询文档
**端点**: `POST /api/v1/{database}/{collection}/find`
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `filter` | object | ❌ | 查询条件(默认 `{}` |
| `projection` | object | ❌ | 字段投影 |
| `sort` | object | ❌ | 排序规则 |
| `skip` | number | ❌ | 跳过文档数 |
| `limit` | number | ❌ | 返回文档数限制 |
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/find \
-H "Content-Type: application/json" \
-d '{
"filter": {
"age": {"$gte": 25, "$lte": 30},
"department": "技术部"
},
"projection": {
"name": 1,
"email": 1,
"_id": 0
},
"sort": {"age": -1},
"limit": 10
}'
```
**响应**:
```json
{
"ok": 1,
"cursor": {
"firstBatch": [
{"name": "Alice", "email": "alice@example.com"},
{"name": "Bob", "email": "bob@example.com"}
],
"id": 0,
"ns": "testdb.users"
}
}
```
### 查询单个文档
**端点**: `POST /api/v1/{database}/{collection}/findOne`
**请求参数**: 同 `find`
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/findOne \
-H "Content-Type: application/json" \
-d '{"filter": {"email": "alice@example.com"}}'
```
**响应**:
```json
{
"ok": 1,
"value": {
"_id": "20240101120000.000000000",
"name": "Alice",
"age": 30,
"email": "alice@example.com"
}
}
```
### 统计文档数
**端点**: `POST /api/v1/{database}/{collection}/count`
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `filter` | object | ❌ | 查询条件(默认 `{}` |
| `limit` | number | ❌ | 最大计数限制 |
| `skip` | number | ❌ | 跳过文档数 |
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/count \
-H "Content-Type: application/json" \
-d '{"filter": {"age": {"$gte": 25}}}'
```
**响应**:
```json
{
"ok": 1,
"n": 15
}
```
---
## 更新操作
### 更新单个文档
**端点**: `POST /api/v1/{database}/{collection}/update`
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `filter` | object | ✅ | 查询条件 |
| `update` | object | ✅ | 更新操作 |
| `upsert` | boolean | ❌ | 不存在则插入(默认 false |
| `multi` | boolean | ❌ | 更新多个(默认 false |
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/update \
-H "Content-Type: application/json" \
-d '{
"filter": {"name": "Alice"},
"update": {
"$set": {"age": 31},
"$inc": {"loginCount": 1}
}
}'
```
**响应**:
```json
{
"ok": 1,
"n": 1,
"nModified": 1,
"matchedCount": 1,
"modifiedCount": 1,
"upsertedId": null
}
```
### 更新多个文档
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/update \
-H "Content-Type: application/json" \
-d '{
"filter": {"department": "技术部"},
"update": {"$inc": {"salary": 1000}},
"multi": true
}'
```
### Upsert 操作
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/update \
-H "Content-Type: application/json" \
-d '{
"filter": {"email": "charlie@example.com"},
"update": {
"$setOnInsert": {
"email": "charlie@example.com",
"name": "Charlie",
"age": 28
}
},
"upsert": true
}'
```
**响应**:
```json
{
"ok": 1,
"n": 1,
"nModified": 0,
"upsertedId": "20240101120002.000000000"
}
```
---
## 删除操作
### 删除单个文档
**端点**: `POST /api/v1/{database}/{collection}/delete`
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `filter` | object | ✅ | 查询条件 |
| `multi` | boolean | ❌ | 删除多个(默认 false |
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/delete \
-H "Content-Type: application/json" \
-d '{"filter": {"email": "alice@example.com"}}'
```
**响应**:
```json
{
"ok": 1,
"n": 1,
"deletedCount": 1
}
```
### 删除多个文档
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/delete \
-H "Content-Type: application/json" \
-d '{
"filter": {"status": "inactive"},
"multi": true
}'
```
---
## 聚合操作
### 执行聚合管道
**端点**: `POST /api/v1/{database}/{collection}/aggregate`
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `pipeline` | array | ✅ | 聚合管道数组 |
| `cursor` | object | ❌ | 游标选项 |
| `explain` | boolean | ❌ | 是否返回执行计划 |
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/orders/aggregate \
-H "Content-Type: application/json" \
-d '{
"pipeline": [
{
"$match": {
"status": "completed",
"createdAt": {"$gte": "2024-01-01"}
}
},
{
"$group": {
"_id": "$customerId",
"totalAmount": {"$sum": "$amount"},
"orderCount": {"$sum": 1},
"avgAmount": {"$avg": "$amount"}
}
},
{
"$sort": {"totalAmount": -1}
},
{
"$limit": 10
}
]
}'
```
**响应**:
```json
{
"ok": 1,
"cursor": {
"firstBatch": [
{
"_id": "cust_001",
"totalAmount": 15000,
"orderCount": 5,
"avgAmount": 3000
},
{
"_id": "cust_002",
"totalAmount": 12000,
"orderCount": 4,
"avgAmount": 3000
}
],
"id": 0,
"ns": "testdb.orders"
}
}
```
### 支持的聚合阶段
详见 [聚合管道文档](AGGREGATION_PIPELINE.md)
---
## 索引管理
### 创建索引
**端点**: `POST /api/v1/{database}/{collection}/createIndex`
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `keys` | object | ✅ | 索引键定义 |
| `unique` | boolean | ❌ | 是否唯一索引 |
| `name` | string | ❌ | 索引名称 |
| `background` | boolean | ❌ | 后台创建(默认 false |
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/createIndex \
-H "Content-Type: application/json" \
-d '{
"keys": {"email": 1},
"unique": true,
"name": "idx_email_unique"
}'
```
**响应**:
```json
{
"ok": 1,
"createdCollectionAutomatically": false,
"numIndexesBefore": 1,
"numIndexesAfter": 2,
"note": "all indexes already exist"
}
```
### 列出索引
**端点**: `POST /api/v1/{database}/{collection}/getIndexes`
**请求**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/getIndexes
```
**响应**:
```json
{
"ok": 1,
"indexes": [
{
"v": 2,
"key": {"_id": 1},
"name": "_id_",
"ns": "testdb.users"
},
{
"v": 2,
"key": {"email": 1},
"name": "idx_email_unique",
"unique": true,
"ns": "testdb.users"
}
]
}
```
### 删除索引
**端点**: `POST /api/v1/{database}/{collection}/dropIndex`
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `index` | string | ✅ | 索引名称 |
**请求示例**:
```bash
curl -X POST http://localhost:8080/api/v1/testdb/users/dropIndex \
-H "Content-Type: application/json" \
-d '{"index": "idx_email_unique"}'
```
**响应**:
```json
{
"ok": 1,
"nIndexesWas": 2
}
```
---
## 错误处理
### 错误响应格式
```json
{
"ok": 0,
"errmsg": "错误描述信息",
"code": 错误码,
"codeName": "错误名称"
}
```
### 常见错误码
| 错误码 | 错误名称 | 说明 |
|--------|---------|------|
| 1 | InternalError | 内部错误 |
| 2 | BadValue | 参数值错误 |
| 7 | NoSuchKey | 键不存在 |
| 11000 | DuplicateKey | 重复键值 |
| 26 | NamespaceNotFound | 集合不存在 |
| 43 | NamespaceExists | 集合已存在 |
| 52 | InvalidPipelineOperator | 无效的聚合操作符 |
### 错误处理示例
**请求重复键值**:
```json
// 请求
{
"documents": [{"email": "existing@example.com"}]
}
// 响应
{
"ok": 0,
"errmsg": "duplicate key error",
"code": 11000,
"codeName": "DuplicateKey"
}
```
---
## 响应格式
### 成功响应
```json
{
"ok": 1,
// 其他响应数据...
}
```
### 分页响应
```json
{
"ok": 1,
"cursor": {
"firstBatch": [...],
"nextBatch": [...],
"id": 12345,
"ns": "database.collection"
}
}
```
### 批量操作响应
```json
{
"ok": 1,
"n": 10,
"insertedIds": {"0": "id1", "1": "id2"},
"upsertedIds": {},
"matchedCount": 10,
"modifiedCount": 8,
"deletedCount": 0
}
```
---
## 高级查询
### 查询操作符
详见 [查询操作符文档](QUERY_OPERATORS.md)
#### 比较操作符
```json
{
"filter": {
"age": {"$gt": 25},
"salary": {"$gte": 5000, "$lte": 10000},
"status": {"$in": ["active", "pending"]}
}
}
```
#### 逻辑操作符
```json
{
"filter": {
"$or": [
{"age": {"$lt": 25}},
{"salary": {"$gt": 8000}}
]
}
}
```
#### 元素操作符
```json
{
"filter": {
"tags": {"$elemMatch": {"$eq": "important"}},
"score": {"$exists": true}
}
}
```
### 更新操作符
详见 [更新操作符文档](UPDATE_OPERATORS.md)
#### 字段更新
```json
{
"update": {
"$set": {"status": "active"},
"$unset": {"tempField": ""},
"$rename": {"oldName": "newName"}
}
}
```
#### 数组操作
```json
{
"update": {
"$push": {"scores": 95},
"$addToSet": {"tags": "new"},
"$pull": {"items": {"price": {"$lt": 100}}}
}
}
```
#### 算术更新
```json
{
"update": {
"$inc": {"viewCount": 1},
"$mul": {"price": 0.9}
}
}
```
---
## 性能优化
### 使用投影
```bash
# 只返回需要的字段
{"projection": {"name": 1, "email": 1, "_id": 0}}
```
### 使用索引
```bash
# 为常用查询字段创建索引
{"keys": {"email": 1, "status": 1}}
```
### 限制结果集
```bash
# 总是使用 limit
{"limit": 100}
```
### 避免全表扫描
```bash
# ❌ 不推荐
{"filter": {"$expr": {"$gt": ["$field1", "$field2"]}}}
# ✅ 推荐
{"filter": {"field1": {"$gt": 100}}}
```
---
## 最佳实践
### 1. 批量操作
```bash
# 批量插入而不是逐条插入
{"documents": [{...}, {...}, {...}]}
```
### 2. 合理使用 upsert
```bash
# 使用 $setOnInsert 避免覆盖现有数据
{
"filter": {"email": "user@example.com"},
"update": {"$setOnInsert": {"name": "User"}},
"upsert": true
}
```
### 3. 事务性操作
对于需要事务的场景,使用 PostgreSQL 或 DM8 作为底层数据库。
### 4. 监控慢查询
```yaml
log:
level: "debug"
slow_query_threshold: "100ms"
```
---
## 附录
### HTTP 状态码
| 状态码 | 说明 |
|--------|------|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
### 数据类型映射
| MongoDB | SQLite | PostgreSQL |
|---------|--------|------------|
| String | TEXT | VARCHAR |
| Number | REAL | DOUBLE PRECISION |
| Integer | INTEGER | BIGINT |
| Boolean | INTEGER | BOOLEAN |
| Array | JSONB | JSONB |
| Object | JSONB | JSONB |
| Date | DATETIME | TIMESTAMP |
---
**维护者**: Gomog Team
**许可证**: MIT

549
manual/QUERY_OPERATORS.md Normal file
View File

@ -0,0 +1,549 @@
# Gomog 查询操作符参考文档
**版本**: v1.0.0-alpha
**最后更新**: 2026-03-14
---
## 📖 目录
1. [比较操作符](#比较操作符)
2. [逻辑操作符](#逻辑操作符)
3. [元素操作符](#元素操作符)
4. [数组操作符](#数组操作符)
5. [正则表达式操作符](#正则表达式操作符)
6. [位运算操作符](#位运算操作符)
7. [使用示例](#使用示例)
---
## 比较操作符
### $eq - 等于
匹配等于指定值的文档。
**语法**:
```json
{"field": {"$eq": <value>}}
// 或简写
{"field": <value>}
```
**示例**:
```json
{"age": {"$eq": 30}}
// 等价于
{"age": 30}
```
### $ne - 不等于
匹配不等于指定值的文档。
**语法**:
```json
{"field": {"$ne": <value>}}
```
**示例**:
```json
{"status": {"$ne": "inactive"}}
```
### $gt - 大于
匹配大于指定值的文档。
**语法**:
```json
{"field": {"$gt": <value>}}
```
**示例**:
```json
{"price": {"$gt": 100}}
```
### $gte - 大于等于
匹配大于或等于指定值的文档。
**语法**:
```json
{"field": {"$gte": <value>}}
```
**示例**:
```json
{"age": {"$gte": 18}}
```
### $lt - 小于
匹配小于指定值的文档。
**语法**:
```json
{"field": {"$lt": <value>}}
```
**示例**:
```json
{"score": {"$lt": 60}}
```
### $lte - 小于等于
匹配小于或等于指定值的文档。
**语法**:
```json
{"field": {"$lte": <value>}}
```
**示例**:
```json
{"quantity": {"$lte": 10}}
```
### $in - 在数组中
匹配值在指定数组中的文档。
**语法**:
```json
{"field": {"$in": [<value1>, <value2>, ...]}}
```
**示例**:
```json
{"status": {"$in": ["active", "pending"]}}
{"age": {"$in": [18, 25, 30]}}
```
### $nin - 不在数组中
匹配值不在指定数组中的文档。
**语法**:
```json
{"field": {"$nin": [<value1>, <value2>, ...]}}
```
**示例**:
```json
{"category": {"$nin": ["deleted", "archived"]}}
```
---
## 逻辑操作符
### $and - 与
匹配所有条件都满足的文档。
**语法**:
```json
{"$and": [{"condition1"}, {"condition2"}, ...]}
```
**示例**:
```json
{
"$and": [
{"age": {"$gte": 18}},
{"status": {"$eq": "active"}}
]
}
// 可简写为
{"age": {"$gte": 18}, "status": "active"}
```
### $or - 或
匹配至少一个条件满足的文档。
**语法**:
```json
{"$or": [{"condition1"}, {"condition2"}, ...]}
```
**示例**:
```json
{
"$or": [
{"age": {"$lt": 18}},
{"senior": true}
]
}
```
### $not - 非
反转条件的结果。
**语法**:
```json
{"field": {"$not": {<expression>}}}
```
**示例**:
```json
{"price": {"$not": {"$gt": 100}}}
```
### $nor - 或非
匹配所有条件都不满足的文档。
**语法**:
```json
{"$nor": [{"condition1"}, {"condition2"}, ...]}
```
**示例**:
```json
{
"$nor": [
{"status": "draft"},
{"archived": true}
]
}
```
---
## 元素操作符
### $exists - 字段存在
匹配包含或不包含指定字段的文档。
**语法**:
```json
{"field": {"$exists": <boolean>}}
```
**示例**:
```json
// 包含 email 字段的文档
{"email": {"$exists": true}}
// 不包含 phone 字段的文档
{"phone": {"$exists": false}}
```
### $type - 类型检查
匹配字段类型等于指定类型的文档。
**语法**:
```json
{"field": {"$type": <BSON type>}}
```
**支持的类型**:
- `"string"`: 字符串
- `"int"` / `"long"`: 整数
- `"double"`: 浮点数
- `"bool"`: 布尔值
- `"array"`: 数组
- `"object"`: 对象
- `"null"`: null 值
- `"date"`: 日期
**示例**:
```json
{"age": {"$type": "int"}}
{"data": {"$type": "array"}}
{"value": {"$type": "null"}}
```
---
## 数组操作符
### $all - 包含所有
匹配数组包含所有指定元素的文档。
**语法**:
```json
{"field": {"$all": [<value1>, <value2>, ...]}}
```
**示例**:
```json
{"tags": {"$all": ["mongodb", "database", "nosql"]}}
```
### $elemMatch - 元素匹配
匹配数组中至少有一个元素满足条件的文档。
**语法**:
```json
{"field": {"$elemMatch": {<query>}}}
```
**示例**:
```json
// 数组中有元素大于 80
{"scores": {"$elemMatch": {"$gt": 80}}}
// 数组中有对象满足多个条件
{"results": {"$elemMatch": {
"product": "laptop",
"price": {"$lt": 1000}
}}}
```
### $size - 数组大小
匹配数组长度等于指定值的文档。
**语法**:
```json
{"field": {"$size": <number>}}
```
**示例**:
```json
{"tags": {"$size": 3}}
```
---
## 正则表达式操作符
### $regex - 正则匹配
使用正则表达式匹配字符串。
**语法**:
```json
{"field": {"$regex": <pattern>, "$options": <options>}}
```
**选项**:
- `i`: 不区分大小写
- `m`: 多行匹配
- `s`: 单行模式(`.` 匹配换行)
- `x`: 扩展模式(忽略空白)
**示例**:
```json
// 以 "john" 开头
{"name": {"$regex": "^john"}}
// 包含 "test",不区分大小写
{"title": {"$regex": "test", "$options": "i"}}
// 邮箱格式验证
{"email": {"$regex": "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"}}
```
---
## 位运算操作符
### $bitsAllClear - 所有指定位为 0
匹配所有指定位都为 0 的文档。
**语法**:
```json
{"field": {"$bitsAllClear": <bitmask>}}
```
**示例**:
```json
{"flags": {"$bitsAllClear": 8}} // 第 4 位为 0
```
### $bitsAllSet - 所有指定位为 1
匹配所有指定位都为 1 的文档。
**语法**:
```json
{"field": {"$bitsAllSet": <bitmask>}}
```
**示例**:
```json
{"permissions": {"$bitsAllSet": 7}} // 第 1-3 位都为 1
```
### $bitsAnyClear - 任意指定位为 0
匹配任意指定位为 0 的文档。
**语法**:
```json
{"field": {"$bitsAnyClear": <bitmask>}}
```
**示例**:
```json
{"status": {"$bitsAnyClear": 15}}
```
### $bitsAnySet - 任意指定位为 1
匹配任意指定位为 1 的文档。
**语法**:
```json
{"field": {"$bitsAnySet": <bitmask>}}
```
**示例**:
```json
{"flags": {"$bitsAnySet": 1}} // 第 1 位为 1
```
---
## 特殊操作符
### $expr - 表达式
允许在查询中使用聚合表达式。
**语法**:
```json
{"$expr": {<expression>}}
```
**示例**:
```json
// 比较两个字段
{"$expr": {"$gt": ["$salary", "$expenses"]}}
// 复杂计算
{"$expr": {"$lt": [{"$multiply": ["$price", "$quantity"]}, 100]}}
```
### $jsonSchema - JSON Schema 验证
使用 JSON Schema 验证文档。
**语法**:
```json
{"$jsonSchema": {<schema>}}
```
**示例**:
```json
{
"$jsonSchema": {
"bsonType": "object",
"required": ["name", "age"],
"properties": {
"name": {"bsonType": "string"},
"age": {"bsonType": "int", "minimum": 0}
}
}
}
```
### $mod - 模运算
匹配除以指定数的余数。
**语法**:
```json
{"field": {"$mod": [<divisor>, <remainder>]}}
```
**示例**:
```json
// 偶数
{"count": {"$mod": [2, 0]}}
// 除以 5 余 3
{"number": {"$mod": [5, 3]}}
```
### $where - JavaScript 表达式
使用 JavaScript 表达式进行匹配(性能较低)。
**语法**:
```json
{"$where": "<javascript>"}
```
**示例**:
```json
{"$where": "this.age > 18 && this.status === 'active'"}
```
---
## 使用示例
### 组合查询
```json
{
"age": {"$gte": 18, "$lte": 65},
"status": "active",
"role": {"$in": ["admin", "user"]},
"$or": [
{"verified": true},
{"score": {"$gte": 80}}
]
}
```
### 嵌套字段查询
```json
{
"address.city": "Beijing",
"contact.email": {"$regex": "@example.com$"}
}
```
### 数组查询
```json
{
"skills": {"$all": ["Go", "Python"]},
"projects": {"$elemMatch": {
"status": "completed",
"budget": {"$gte": 10000}
}}
}
```
### 复杂逻辑查询
```json
{
"$or": [
{
"$and": [
{"age": {"$gte": 18}},
{"senior": true}
]
},
{
"$and": [
{"age": {"$gte": 65}},
{"retired": true}
]
}
],
"status": {"$ne": "banned"}
}
```
---
**维护者**: Gomog Team
**许可证**: MIT

277
manual/QUICK_REFERENCE.md Normal file
View File

@ -0,0 +1,277 @@
# Gomog 快速参考手册
**版本**: v1.0.0-alpha
**最后更新**: 2026-03-14
---
## 📖 目录
1. [常用命令速查](#常用命令速查)
2. [操作符速查表](#操作符速查表)
3. [聚合阶段速查表](#聚合阶段速查表)
4. [数据类型映射](#数据类型映射)
5. [错误码速查](#错误码速查)
---
## 常用命令速查
### HTTP API 基础
```bash
# 健康检查
curl http://localhost:8080/health
# 插入文档
curl -X POST http://localhost:8080/api/v1/{db}/{collection}/insert \
-H "Content-Type: application/json" \
-d '{"documents": [{...}]}'
# 查询文档
curl -X POST http://localhost:8080/api/v1/{db}/{collection}/find \
-H "Content-Type: application/json" \
-d '{"filter": {...}}'
# 更新文档
curl -X POST http://localhost:8080/api/v1/{db}/{collection}/update \
-H "Content-Type: application/json" \
-d '{"filter": {...}, "update": {...}}'
# 删除文档
curl -X POST http://localhost:8080/api/v1/{db}/{collection}/delete \
-H "Content-Type: application/json" \
-d '{"filter": {...}}'
# 聚合管道
curl -X POST http://localhost:8080/api/v1/{db}/{collection}/aggregate \
-H "Content-Type: application/json" \
-d '{"pipeline": [...]}'
```
### MongoDB Shell
```javascript
// 连接
mongosh --host localhost --port 27017
// 基本 CRUD
db.collection.insertOne({field: "value"})
db.collection.find({field: {$gt: 10}})
db.collection.updateOne({field: 1}, {$set: {field: 2}})
db.collection.deleteOne({field: 1})
// 聚合
db.collection.aggregate([
{$match: {status: "active"}},
{$group: {_id: "$category", count: {$sum: 1}}}
])
```
---
## 操作符速查表
### 比较操作符
| 操作符 | 说明 | 示例 |
|--------|------|------|
| `$eq` | 等于 | `{"age": {"$eq": 18}}` |
| `$ne` | 不等于 | `{"status": {"$ne": "deleted"}}` |
| `$gt` | 大于 | `{"price": {"$gt": 100}}` |
| `$gte` | 大于等于 | `{"score": {"$gte": 60}}` |
| `$lt` | 小于 | `{"quantity": {"$lt": 10}}` |
| `$lte` | 小于等于 | `{"age": {"$lte": 65}}` |
| `$in` | 在数组中 | `{"status": {"$in": ["a","b"]}}` |
| `$nin` | 不在数组中 | `{"type": {"$nin": ["x","y"]}}` |
### 逻辑操作符
| 操作符 | 说明 | 示例 |
|--------|------|------|
| `$and` | 与 | `{"$and": [{a:1}, {b:2}]}` |
| `$or` | 或 | `{"$or": [{a:1}, {b:2}]}` |
| `$not` | 非 | `{"price": {"$not": {"$gt": 100}}}` |
| `$nor` | 或非 | `{"$nor": [{a:1}, {b:2}]}` |
### 元素操作符
| 操作符 | 说明 | 示例 |
|--------|------|------|
| `$exists` | 字段存在 | `{"email": {"$exists": true}}` |
| `$type` | 类型检查 | `{"age": {"$type": "int"}}` |
### 数组操作符
| 操作符 | 说明 | 示例 |
|--------|------|------|
| `$all` | 包含所有 | `{"tags": {"$all": ["a","b"]}}` |
| `$elemMatch` | 元素匹配 | `{"scores": {"$elemMatch": {"$gt": 80}}}` |
| `$size` | 数组大小 | `{"items": {"$size": 5}}` |
### 更新操作符
| 操作符 | 说明 | 示例 |
|--------|------|------|
| `$set` | 设置字段 | `{"$set": {name: "test"}}` |
| `$unset` | 移除字段 | `{"$unset": {oldField: ""}}` |
| `$inc` | 递增 | `{"$inc": {count: 1}}` |
| `$mul` | 乘法 | `{"$mul": {price: 0.9}}` |
| `$push` | 推入数组 | `{"$push": {tags: "new"}}` |
| `$pull` | 拉出数组 | `{"$pull": {tags: "old"}}` |
| `$addToSet` | 添加到集合 | `{"$addToSet": {ids: 123}}` |
| `$pop` | 弹出元素 | `{"$pop": {items: 1}}` |
---
## 聚合阶段速查表
### 数据过滤
| 阶段 | 说明 | 示例 |
|------|------|------|
| `$match` | 过滤文档 | `{$match: {status: "active"}}` |
| `$limit` | 限制数量 | `{$limit: 10}` |
| `$skip` | 跳过数量 | `{$skip: 20}` |
| `$sample` | 随机采样 | `{$sample: {size: 5}}` |
| `$bucket` | 分桶分组 | `{$bucket: {groupBy: "$price", boundaries: [0,100]}}` |
### 数据转换
| 阶段 | 说明 | 示例 |
|------|------|------|
| `$project` | 重塑文档 | `{$project: {name: 1, _id: 0}}` |
| `$addFields` | 添加字段 | `{$addFields: {total: {$add: ["$a","$b"]}}}` |
| `$unset` | 移除字段 | `{$unset: ["temp"]}` |
| `$replaceRoot` | 替换根文档 | `{$replaceRoot: {newRoot: "$user"}}` |
### 数据分组
| 阶段 | 说明 | 示例 |
|------|------|------|
| `$group` | 分组聚合 | `{$group: {_id: "$dept", avg: {$avg: "$salary"}}}` |
| `$sort` | 排序 | `{$sort: {createdAt: -1}}` |
| `$sortByCount` | 分组计数 | `{$sortByCount: "$category"}` |
### 关联查询
| 阶段 | 说明 | 示例 |
|------|------|------|
| `$lookup` | 左外连接 | `{$lookup: {from: "orders", localField: "_id", foreignField: "userId", as: "orders"}}` |
| `$graphLookup` | 递归查找 | `{$graphLookup: {from: "orgs", startWith: "$parentId", connectFromField: "_id", connectToField: "parentId", as: "subOrgs"}}` |
| `$unwind` | 展开数组 | `{$unwind: "$tags"}` |
### 性能优化
| 阶段 | 说明 | 示例 |
|------|------|------|
| `$facet` | 多面聚合 | `{$facet: {data: [...], stats: [...]}}` |
| `$indexStats` | 索引统计 | `{$indexStats: {}}` |
| `$setWindowFields` | 窗口函数 | `{$setWindowFields: {partitionBy: "$region", output: {rank: {$documentNumber: {}}}}}` |
### 累加器
| 操作符 | 说明 | 示例 |
|--------|------|------|
| `$sum` | 求和 | `{total: {$sum: "$amount"}}` |
| `$avg` | 平均值 | `{avg: {$avg: "$score"}}` |
| `$min` | 最小值 | `{min: {$min: "$price"}}` |
| `$max` | 最大值 | `{max: {$max: "$quantity"}}` |
| `$push` | 推入数组 | `{items: {$push: "$$ROOT"}}` |
| `$addToSet` | 添加到集合 | `{unique: {$addToSet: "$tag"}}` |
| `$first` | 第一个值 | `{first: {$first: "$name"}}` |
| `$last` | 最后一个值 | `{last: {$last: "$value"}}` |
| `$count` | 计数 | `{cnt: {$count: {}}}` |
---
## 数据类型映射
### BSON 类型对应表
| BSON 类型 | JavaScript | Go | Python | SQL |
|-----------|------------|----|---------|-----|
| String | String | string | str | VARCHAR |
| Int32 | Number | int32 | int | INTEGER |
| Int64 | BigInt | int64 | int | BIGINT |
| Double | Number | float64 | float | DOUBLE |
| Boolean | Boolean | bool | bool | BOOLEAN |
| Null | null | nil | None | NULL |
| Array | Array | []interface{} | list | JSONB |
| Object | Object | map[string]interface{} | dict | JSONB |
| Date | Date | time.Time | datetime | DATETIME |
| ObjectId | ObjectId | primitive.ObjectID | ObjectId | VARCHAR(24) |
---
## 错误码速查
### 常见错误码
| 错误码 | 错误名称 | 说明 |
|--------|---------|------|
| 1 | InternalError | 内部错误 |
| 2 | BadValue | 参数值错误 |
| 7 | NoSuchKey | 键不存在 |
| 11000 | DuplicateKey | 重复键值 |
| 26 | NamespaceNotFound | 集合不存在 |
| 43 | NamespaceExists | 集合已存在 |
| 52 | InvalidPipelineOperator | 无效的聚合操作符 |
### HTTP 状态码
| 状态码 | 说明 |
|--------|------|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
---
## 配置文件示例
```yaml
server:
http_addr: ":8080"
tcp_addr: ":27017"
mode: "dev"
database:
type: "sqlite"
dsn: "gomog.db"
max_open: 10
max_idle: 5
log:
level: "info"
format: "text"
```
---
## 环境变量
| 变量 | 配置项 | 默认值 |
|------|--------|---------|
| `GOMOG_HTTP_ADDR` | server.http_addr | :8080 |
| `GOMOG_TCP_ADDR` | server.tcp_addr | :27017 |
| `GOMOG_DB_TYPE` | database.type | sqlite |
| `GOMOG_DB_DSN` | database.dsn | gomog.db |
| `GOMOG_LOG_LEVEL` | log.level | info |
---
## 相关链接
- [用户手册](USER_GUIDE.md)
- [HTTP API 参考](HTTP_API.md)
- [TCP 协议参考](TCP_PROTOCOL.md)
- [聚合管道参考](AGGREGATION_PIPELINE.md)
- [查询操作符参考](QUERY_OPERATORS.md)
- [更新操作符参考](UPDATE_OPERATORS.md)
---
**维护者**: Gomog Team
**许可证**: MIT

213
manual/README.md Normal file
View File

@ -0,0 +1,213 @@
# Gomog 用户手册与 API 文档
**版本**: v1.0.0-alpha
**最后更新**: 2026-03-14
**许可证**: MIT
---
## 📚 文档导航
本目录包含 Gomog 的完整用户手册和 API 参考文档。
### 快速开始
1. **新用户必读**: [用户指南](USER_GUIDE.md) - 完整的入门教程
2. **快速参考**: [快速参考手册](QUICK_REFERENCE.md) - 常用命令速查
3. **示例代码**: [API 使用示例](../doc/API_EXAMPLES.md) - 实际使用案例
---
## 📖 文档分类
### 📘 用户指南
| 文档 | 说明 | 适合人群 |
|------|------|----------|
| [USER_GUIDE.md](USER_GUIDE.md) | **完整用户手册** - 安装、配置、使用、最佳实践 | 所有用户 |
| [QUICK_REFERENCE.md](QUICK_REFERENCE.md) | **快速参考手册** - 操作符、命令、错误码速查 | 所有用户 |
### 🌐 API 参考
#### HTTP API
| 文档 | 说明 | 适合人群 |
|------|------|----------|
| [HTTP_API.md](HTTP_API.md) | **HTTP API 完整参考** - RESTful API、端点、参数、示例 | 后端开发者 |
| [QUERY_OPERATORS.md](QUERY_OPERATORS.md) | **查询操作符参考** - 16+ 个查询操作符详解 | 查询开发者 |
| [UPDATE_OPERATORS.md](UPDATE_OPERATORS.md) | **更新操作符参考** - 17+ 个更新操作符详解 | 查询开发者 |
#### TCP 协议
| 文档 | 说明 | 适合人群 |
|------|------|----------|
| [TCP_PROTOCOL.md](TCP_PROTOCOL.md) | **TCP 协议参考** - MongoDB Wire Protocol 兼容实现 | 客户端开发者 |
### 🔧 高级功能
| 文档 | 说明 | 适合人群 |
|------|------|----------|
| [AGGREGATION_PIPELINE.md](AGGREGATION_PIPELINE.md) | **聚合管道完整参考** - 18+ 阶段、50+ 表达式 | 数据分析师 |
---
## 🎯 按使用场景查找
### 我是新手,第一次使用 Gomog
1. 阅读 [用户指南](USER_GUIDE.md) 了解基本概念
2. 查看 [快速参考](QUICK_REFERENCE.md) 熟悉常用命令
3. 参考 [API 使用示例](../doc/API_EXAMPLES.md) 上手实践
### 我想使用 HTTP API 开发应用
1. 查阅 [HTTP API 参考](HTTP_API.md) 了解所有端点
2. 参考 [查询操作符](QUERY_OPERATORS.md) 构建复杂查询
3. 查看 [更新操作符](UPDATE_OPERATORS.md) 实现数据更新
### 我想使用 MongoDB 客户端连接
1. 阅读 [TCP 协议参考](TCP_PROTOCOL.md) 了解连接方式
2. 查看各语言示例Node.js、Python、Go
3. 参考 [快速参考](QUICK_REFERENCE.md) 熟悉命令映射
### 我想进行复杂数据分析
1. 学习 [聚合管道参考](AGGREGATION_PIPELINE.md)
2. 查看实用示例(电商分析、用户行为、社交网络)
3. 参考 [性能优化](AGGREGATION_PIPELINE.md#性能调优) 章节
### 我需要排查问题
1. 查看 [用户指南 - 故障排查](USER_GUIDE.md#故障排查) 章节
2. 参考 [快速参考 - 错误码](QUICK_REFERENCE.md#错误码速查)
3. 查阅 [常见问题](USER_GUIDE.md#常见问题)
---
## 📊 文档统计
| 类别 | 文档数 | 总大小 |
|------|--------|--------|
| 用户指南 | 2 | ~30KB |
| API 参考 | 4 | ~80KB |
| 高级功能 | 1 | ~25KB |
| **总计** | **7** | **~135KB** |
---
## 🔍 快速查找表
### 常用操作
| 操作 | HTTP API | MongoDB Shell | 文档链接 |
|------|---------|---------------|----------|
| 插入文档 | `POST /insert` | `insertOne()` | [HTTP API](HTTP_API.md#插入文档) |
| 查询文档 | `POST /find` | `find()` | [HTTP API](HTTP_API.md#查询文档) |
| 更新文档 | `POST /update` | `updateOne()` | [HTTP API](HTTP_API.md#更新操作) |
| 删除文档 | `POST /delete` | `deleteOne()` | [HTTP API](HTTP_API.md#删除操作) |
| 聚合管道 | `POST /aggregate` | `aggregate()` | [HTTP API](HTTP_API.md#聚合操作) |
| 创建索引 | `POST /createIndex` | `createIndex()` | [HTTP API](HTTP_API.md#索引管理) |
### 常用操作符
| 类型 | 操作符 | 说明 | 文档链接 |
|------|--------|------|----------|
| 比较 | `$eq`, `$ne`, `$gt`, `$lt` | 基本比较 | [查询操作符](QUERY_OPERATORS.md#比较操作符) |
| 逻辑 | `$and`, `$or`, `$not` | 逻辑运算 | [查询操作符](QUERY_OPERATORS.md#逻辑操作符) |
| 数组 | `$all`, `$elemMatch`, `$size` | 数组操作 | [查询操作符](QUERY_OPERATORS.md#数组操作符) |
| 更新 | `$set`, `$inc`, `$push` | 字段更新 | [更新操作符](UPDATE_OPERATORS.md) |
| 聚合 | `$match`, `$group`, `$sort` | 聚合阶段 | [聚合管道](AGGREGATION_PIPELINE.md) |
---
## 💡 学习路径建议
### 基础篇1-2 天)
1. ✅ 阅读 [用户指南](USER_GUIDE.md) 第 1-3 章
2. ✅ 完成 [快速开始](USER_GUIDE.md#快速开始) 示例
3. ✅ 熟悉 [快速参考](QUICK_REFERENCE.md)
### 进阶篇3-5 天)
1. ✅ 深入学习 [HTTP API](HTTP_API.md)
2. ✅ 掌握 [查询操作符](QUERY_OPERATORS.md)
3. ✅ 练习 [更新操作符](UPDATE_OPERATORS.md)
### 高级篇1-2 周)
1. ✅ 精通 [聚合管道](AGGREGATION_PIPELINE.md)
2. ✅ 了解 [TCP 协议](TCP_PROTOCOL.md)
3. ✅ 实践 [最佳实践](USER_GUIDE.md#最佳实践)
---
## 📝 文档更新记录
| 日期 | 文档 | 更新内容 |
|------|------|----------|
| 2026-03-14 | 所有文档 | 初始版本发布 |
---
## 🆘 获取帮助
### 文档相关问题
- 查看对应文档的详细说明
- 参考示例代码
- 查阅常见问题
### 技术问题
- GitHub Issues: 提交 bug 报告
- GitHub Discussions: 发起讨论
- 社区论坛:寻求社区帮助
### 联系方式
- **项目主页**: https://github.com/gomog/gomog
- **问题反馈**: https://github.com/gomog/gomog/issues
- **讨论区**: https://github.com/gomog/gomog/discussions
---
## 📋 文档结构
```
manual/
├── README.md # 本文档索引
├── USER_GUIDE.md # 用户指南
├── QUICK_REFERENCE.md # 快速参考手册
├── HTTP_API.md # HTTP API 参考
├── TCP_PROTOCOL.md # TCP 协议参考
├── AGGREGATION_PIPELINE.md # 聚合管道参考
├── QUERY_OPERATORS.md # 查询操作符参考
└── UPDATE_OPERATORS.md # 更新操作符参考
```
---
## ⭐ 推荐资源
### 官方文档
- [MongoDB 官方文档](https://www.mongodb.com/docs/)
- [BSON 规范](http://bsonspec.org/)
### 社区资源
- MongoDB University 免费课程
- Stack Overflow MongoDB 标签
- Reddit r/mongodb 社区
---
**维护者**: Gomog Team
**贡献者**: 查看 GitHub 贡献者列表
**许可证**: MIT
---
*最后更新2026-03-14*

692
manual/TCP_PROTOCOL.md Normal file
View File

@ -0,0 +1,692 @@
# Gomog TCP 协议参考文档
**版本**: v1.0.0-alpha
**最后更新**: 2026-03-14
**协议**: MongoDB Wire Protocol (兼容)
---
## 📖 目录
1. [概述](#概述)
2. [消息格式](#消息格式)
3. [操作码](#操作码)
4. [OP_MSG 协议](#op_msg-协议)
5. [使用示例](#使用示例)
6. [客户端开发](#客户端开发)
7. [错误处理](#错误处理)
---
## 概述
### 什么是 TCP 协议?
Gomog 的 TCP 协议实现了 MongoDB Wire Protocol 的兼容层,允许任何 MongoDB 客户端直接连接到 Gomog 服务器,无需修改代码。
### 协议特点
- ✅ **MongoDB 兼容**: 支持标准 MongoDB 线协议
- ✅ **双向通信**: 基于 TCP 的长连接
- ✅ **高效传输**: 二进制协议,低开销
- ✅ **并发安全**: 支持多客户端并发连接
- ✅ **会话管理**: 自动管理连接状态
### 默认配置
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| 监听地址 | `:27017` | MongoDB 默认端口 |
| 最大连接数 | 无限制 | 可配置 |
| 读超时 | 无 | 可配置 |
| 写超时 | 无 | 可配置 |
---
## 消息格式
### 消息头Message Header
所有 MongoDB Wire Protocol 消息都以 16 字节的头部开始:
```
0 4 8 12 13 14 15
+-------------------+-------------------+-----------+--+--+--+--+
| Length | RequestID |ResponseTo |Op|Op|Op|Op|
+-------------------+-------------------+-----------+--+--+--+--+
```
| 字段 | 大小 | 类型 | 说明 |
|------|------|------|------|
| `Length` | 4 bytes | int32 | 消息总长度(包括头部) |
| `RequestID` | 4 bytes | int32 | 请求 ID由客户端生成 |
| `ResponseTo` | 4 bytes | int32 | 响应到的请求 ID服务器响应时使用 |
| `OpCode` | 4 bytes | int32 | 操作码 |
### 字节序
所有多字节字段都使用**小端字节序**Little-Endian
---
## 操作码
### 支持的操作码
| 操作码 | 名称 | 说明 |
|--------|------|------|
| 1 | OP_REPLY | 服务器响应 |
| 4 | OP_UPDATE | 更新文档 |
| 8 | OP_INSERT | 插入文档 |
| 2004 | OP_QUERY | 查询文档 |
| 2006 | OP_GETMORE | 获取更多结果 |
| 2007 | OP_DELETE | 删除文档 |
| 2013 | OP_MSG | 扩展协议消息(主要使用) |
### OP_MSG推荐
OP_MSG 是 MongoDB 3.6+ 引入的扩展协议,支持所有数据库操作。
---
## OP_MSG 协议
### 消息格式
```
0 4 16
+---------------+------------------------------+
| OpCode | Flags |
+---------------+------------------------------+
| Checksum | Sections... |
+--------------+-------------------------------+
```
### 标志位Flags
| 标志 | 值 | 说明 |
|------|-----|------|
| `checksumPresent` | 0x00000001 | 存在校验和 |
| `moreToCome` | 0x00000002 | 更多消息到来 |
### Section 格式
每个 Section 包含:
```
+-------------+------------------+
| Kind (1B) | Data... |
+-------------+------------------+
```
#### Body Section (Kind = 0)
包含主要的命令文档。
#### Document Sequence Section (Kind = 1)
包含文档序列。
### 常用命令
#### insert 命令
```json
{
"insert": "collection_name",
"documents": [
{"_id": 1, "name": "Alice"},
{"_id": 2, "name": "Bob"}
],
"ordered": true
}
```
#### find 命令
```json
{
"find": "collection_name",
"filter": {"age": {"$gt": 25}},
"projection": {"name": 1},
"limit": 10
}
```
#### update 命令
```json
{
"update": "collection_name",
"updates": [
{
"q": {"name": "Alice"},
"u": {"$set": {"age": 31}}
}
]
}
```
#### delete 命令
```json
{
"delete": "collection_name",
"deletes": [
{
"q": {"name": "Bob"},
"limit": 1
}
]
}
```
#### aggregate 命令
```json
{
"aggregate": "collection_name",
"pipeline": [
{"$match": {"status": "active"}},
{"$group": {"_id": "$category", "count": {"$sum": 1}}}
]
}
```
---
## 使用示例
### 使用 MongoDB Shell
```bash
# 连接到 Gomog
mongosh --host localhost --port 27017
# 切换到数据库
use testdb
# 插入文档
db.users.insertOne({name: "Alice", age: 30})
# 批量插入
db.users.insertMany([
{name: "Bob", age: 25},
{name: "Charlie", age: 35}
])
# 查询
db.users.find({age: {$gt: 28}})
# 聚合
db.orders.aggregate([
{$match: {status: "completed"}},
{$group: {_id: "$customerId", total: {$sum: "$amount"}}}
])
# 更新
db.users.updateOne(
{name: "Alice"},
{$set: {age: 31}}
)
# 删除
db.users.deleteOne({name: "Bob"})
```
### 使用 Node.js MongoDB Driver
```javascript
const { MongoClient } = require('mongodb');
async function main() {
// 连接到 Gomog
const client = new MongoClient('mongodb://localhost:27017');
try {
await client.connect();
console.log('Connected to Gomog!');
const db = client.db('testdb');
const users = db.collection('users');
// 插入
await users.insertOne({name: 'Alice', age: 30});
// 查询
const result = await users.findOne({name: 'Alice'});
console.log(result);
// 更新
await users.updateOne(
{name: 'Alice'},
{$set: {age: 31}}
);
// 聚合
const aggResult = await users.aggregate([
{$group: {_id: null, avgAge: {$avg: '$age'}}}
]).toArray();
console.log(aggResult);
} finally {
await client.close();
}
}
main().catch(console.error);
```
### 使用 Python PyMongo
```python
from pymongo import MongoClient
# 连接到 Gomog
client = MongoClient('mongodb://localhost:27017/')
db = client.testdb
users = db.users
# 插入
user = {"name": "Alice", "age": 30}
result = users.insert_one(user)
print(f"Inserted ID: {result.inserted_id}")
# 批量插入
users.insert_many([
{"name": "Bob", "age": 25},
{"name": "Charlie", "age": 35}
])
# 查询
for user in users.find({"age": {"$gt": 28}}):
print(user)
# 更新
result = users.update_one(
{"name": "Alice"},
{"$set": {"age": 31}}
)
print(f"Modified: {result.modified_count}")
# 聚合
pipeline = [
{"$group": {"_id": None, "avgAge": {"$avg": "$age"}}}
]
result = list(users.aggregate(pipeline))
print(result)
```
### 使用 Go MongoDB Driver
```go
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// 连接到 Gomog
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
db := client.Database("testdb")
users := db.Collection("users")
// 插入
_, err = users.InsertOne(ctx, bson.M{"name": "Alice", "age": 30})
if err != nil {
log.Fatal(err)
}
// 查询
var result bson.M
err = users.FindOne(ctx, bson.M{"name": "Alice"}).Decode(&result)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found: %+v\n", result)
// 更新
_, err = users.UpdateOne(
ctx,
bson.M{"name": "Alice"},
bson.M{"$set": bson.M{"age": 31}},
)
if err != nil {
log.Fatal(err)
}
// 聚合
pipeline := mongo.Pipeline{
{{"$group", bson.D{{"_id", nil}, {"avgAge", bson.D{{"$avg", "$age"}}}}}},
}
cursor, err := users.Aggregate(ctx, pipeline)
if err != nil {
log.Fatal(err)
}
defer cursor.Close(ctx)
var results []bson.M
if err = cursor.All(ctx, &results); err != nil {
log.Fatal(err)
}
fmt.Printf("Aggregation: %+v\n", results)
}
```
---
## 客户端开发
### 实现 OP_MSG 解析
```go
package tcp
import (
"encoding/binary"
"io"
)
// ReadMessageHeader 读取消息头
func ReadMessageHeader(r io.Reader) (*MessageHeader, error) {
header := &MessageHeader{}
// 读取 Length
if err := binary.Read(r, binary.LittleEndian, &header.Length); err != nil {
return nil, err
}
// 读取 RequestID
if err := binary.Read(r, binary.LittleEndian, &header.RequestID); err != nil {
return nil, err
}
// 读取 ResponseTo
if err := binary.Read(r, binary.LittleEndian, &header.ResponseTo); err != nil {
return nil, err
}
// 读取 OpCode
if err := binary.Read(r, binary.LittleEndian, &header.OpCode); err != nil {
return nil, err
}
return header, nil
}
// WriteMessage 写入消息
func WriteMessage(w io.Writer, requestID uint32, responseTo uint32, opCode uint32, payload []byte) error {
length := uint32(16 + len(payload))
// 写入 Length
if err := binary.Write(w, binary.LittleEndian, length); err != nil {
return err
}
// 写入 RequestID
if err := binary.Write(w, binary.LittleEndian, requestID); err != nil {
return err
}
// 写入 ResponseTo
if err := binary.Write(w, binary.LittleEndian, responseTo); err != nil {
return err
}
// 写入 OpCode
if err := binary.Write(w, binary.LittleEndian, opCode); err != nil {
return err
}
// 写入 Payload
if _, err := w.Write(payload); err != nil {
return err
}
return nil
}
```
### 处理 OP_MSG
```go
func handleOPMsg(header *MessageHeader, body []byte) ([]byte, error) {
// 解析 Section
kind := body[0]
documentData := body[1:]
// 解析 BSON 文档
var doc bson.Raw
if err := bson.Unmarshal(documentData, &doc); err != nil {
return nil, err
}
// 获取命令
command := doc.Lookup("insert").StringValue()
if command == "" {
command = doc.Lookup("find").StringValue()
}
// 执行相应操作
switch {
case doc.Lookup("insert").Valid():
return handleInsert(doc)
case doc.Lookup("find").Valid():
return handleFind(doc)
case doc.Lookup("update").Valid():
return handleUpdate(doc)
case doc.Lookup("delete").Valid():
return handleDelete(doc)
case doc.Lookup("aggregate").Valid():
return handleAggregate(doc)
default:
return nil, errors.New("unknown command")
}
}
```
---
## 错误处理
### 错误响应格式
```json
{
"ok": 0,
"errmsg": "错误描述",
"code": 错误码,
"codeName": "错误名称"
}
```
### 常见错误
#### 连接错误
```
E11000 duplicate key error
NoSuchKey: key not found
NamespaceNotFound: collection does not exist
```
#### 语法错误
```
BadValue: invalid parameter type
FailedToParse: unable to parse query
Location40352: unsupported operator
```
### 错误处理示例
```javascript
try {
await db.users.insertOne({_id: 1, name: "Alice"});
await db.users.insertOne({_id: 1, name: "Bob"}); // 重复键错误
} catch (error) {
console.error(error.code); // 11000
console.error(error.message); // duplicate key error
}
```
---
## 性能优化
### 1. 使用批量操作
```javascript
// ❌ 不推荐:逐条插入
for (let i = 0; i < 1000; i++) {
await db.users.insertOne({id: i});
}
// ✅ 推荐:批量插入
const docs = Array.from({length: 1000}, (_, i) => ({id: i}));
await db.users.insertMany(docs);
```
### 2. 使用投影
```javascript
// ❌ 不推荐:返回所有字段
db.users.find({status: "active"});
// ✅ 推荐:只返回需要的字段
db.users.find(
{status: "active"},
{projection: {name: 1, email: 1}}
);
```
### 3. 使用索引
```javascript
// 为常用查询创建索引
db.users.createIndex({email: 1});
db.users.createIndex({status: 1, createdAt: -1});
```
### 4. 限制结果集
```javascript
// 总是使用 limit
db.users.find({}).limit(100);
```
---
## 监控与调试
### 查看当前连接
```javascript
// 在 Gomog 服务器日志中查看
tail -f /var/log/gomog/gomog.log | grep "connection"
```
### 慢查询分析
```yaml
# 配置慢查询阈值
log:
level: "debug"
slow_query_threshold: "100ms"
```
### 启用详细日志
```yaml
server:
mode: "dev" # 开发模式会输出详细日志
```
---
## 最佳实践
### 1. 连接池管理
```javascript
const client = new MongoClient(uri, {
maxPoolSize: 10,
minPoolSize: 5,
maxIdleTimeMS: 30000
});
```
### 2. 重试逻辑
```javascript
const session = client.startSession();
await session.withTransaction(async () => {
// 事务操作
}, {
maxCommitTimeMS: 10000,
readConcern: {level: 'local'},
writeConcern: {w: 'majority'}
});
```
### 3. 超时设置
```javascript
const cursor = db.collection.find({}, {
timeout: true
}).maxTimeMS(5000);
```
---
## 附录
### A. 数据类型映射
| BSON 类型 | JavaScript | Go | Python |
|-----------|------------|----|---------|
| String | String | string | str |
| Int32 | Number | int32 | int |
| Int64 | BigInt | int64 | int |
| Double | Number | float64 | float |
| Boolean | Boolean | bool | bool |
| ObjectId | ObjectId | primitive.ObjectID | ObjectId |
| Date | Date | time.Time | datetime |
| Array | Array | []interface{} | list |
| Object | Object | map[string]interface{} | dict |
| Null | null | nil | None |
### B. 保留字段
以下字段名在 Gomog 中有特殊含义:
- `_id`: 文档唯一标识符
- `$*`: 操作符前缀
- `$$`: 系统变量前缀
### C. 相关链接
- [MongoDB Wire Protocol 官方文档](https://www.mongodb.com/docs/manual/reference/mongodb-wire-protocol/)
- [OP_MSG 规范](https://github.com/mongodb/specifications/blob/master/source/message/OP_MSG.rst)
- [BSON 规范](http://bsonspec.org/)
---
**维护者**: Gomog Team
**许可证**: MIT

674
manual/UPDATE_OPERATORS.md Normal file
View File

@ -0,0 +1,674 @@
# Gomog 更新操作符参考文档
**版本**: v1.0.0-alpha
**最后更新**: 2026-03-14
---
## 📖 目录
1. [字段更新操作符](#字段更新操作符)
2. [数组更新操作符](#数组更新操作符)
3. [算术更新操作符](#算术更新操作符)
4. [位运算更新操作符](#位运算更新操作符)
5. [条件更新操作符](#条件更新操作符)
6. [使用示例](#使用示例)
---
## 字段更新操作符
### $set - 设置字段
设置字段的值。如果字段不存在,则创建该字段。
**语法**:
```json
{"$set": {"<field>": <value>}}
```
**示例**:
```json
// 设置单个字段
{"$set": {"status": "active"}}
// 设置多个字段
{
"$set": {
"status": "active",
"lastModified": ISODate("2024-01-01")
}
}
// 设置嵌套字段
{"$set": {"address.city": "Beijing"}}
```
### $unset - 移除字段
移除一个或多个字段。
**语法**:
```json
{"$unset": {"<field>": ""}}
// 或
{"$unset": {"<field1>": "", "<field2>": ""}}
```
**示例**:
```json
// 移除单个字段
{"$unset": {"tempField": ""}}
// 移除多个字段
{
"$unset": {
"oldField": "",
"deprecated": ""
}
}
```
### $setOnInsert - 仅在插入时设置
仅在 upsert 操作创建新文档时设置字段。
**语法**:
```json
{"$setOnInsert": {"<field>": <value>}}
```
**示例**:
```json
{
"$setOnInsert": {
"createdAt": ISODate("2024-01-01"),
"createdBy": "system"
}
}
```
### $rename - 重命名字段
重命名字段名。
**语法**:
```json
{"$rename": {"<oldField>": "<newField>"}}
```
**示例**:
```json
// 重命名单个字段
{"$rename": {"oldName": "newName"}}
// 重命名多个字段
{
"$rename": {
"firstName": "givenName",
"lastName": "familyName"
}
}
```
### $currentDate - 设置为当前时间
将字段设置为当前日期或时间戳。
**语法**:
```json
{"$currentDate": {"<field>": <type>}}
```
**类型**:
- `true`: BSON Date (默认)
- `{$type: "timestamp"}`: BSON Timestamp
**示例**:
```json
// 设置为 Date
{"$currentDate": {"lastModified": true}}
// 设置为 Timestamp
{"$currentDate": {"lastModified": {$type: "timestamp"}}}
```
---
## 数组更新操作符
### $push - 推入元素
向数组中添加一个元素。
**语法**:
```json
{"$push": {"<arrayField>": <value>}}
```
**示例**:
```json
// 添加单个元素
{"$push": {"tags": "mongodb"}}
// 添加对象到数组
{"$push": {"scores": {"value": 95, "date": ISODate("2024-01-01")}}}
// 配合 $each 使用
{
"$push": {
"tags": {
"$each": ["database", "nosql"],
"$sort": 1,
"$slice": 10
}
}
}
```
**修饰符**:
- `$each`: 添加多个值
- `$sort`: 排序数组
- `$slice`: 限制数组大小
- `$position`: 指定插入位置
### $addToSet - 添加到集合
向数组中添加元素(如果不存在)。
**语法**:
```json
{"$addToSet": {"<arrayField>": <value>}}
```
**示例**:
```json
// 添加唯一值
{"$addToSet": {"tags": "database"}}
// 配合 $each 使用
{
"$addToSet": {
"tags": {
"$each": ["mongodb", "nosql", "database"]
}
}
}
```
### $pop - 弹出元素
从数组中移除第一个或最后一个元素。
**语法**:
```json
{"$pop": {"<arrayField>": <direction>}}
```
**方向**:
- `1`: 移除最后一个元素
- `-1`: 移除第一个元素
**示例**:
```json
// 移除最后一个元素
{"$pop": {"items": 1}}
// 移除第一个元素
{"$pop": {"items": -1}}
```
### $pull - 拉出元素
从数组中移除所有匹配的元素。
**语法**:
```json
{"$pull": {"<arrayField>": {<query>}}}
```
**示例**:
```json
// 移除等于特定值的元素
{"$pull": {"tags": "deprecated"}}
// 移除满足条件的元素
{"$pull": {
"items": {
"price": {"$lt": 100}
}
}}
// 移除数组中的对象
{"$pull": {
"users": {
"status": "inactive"
}
}}
```
### $pullAll - 拉出多个元素
从数组中移除多个指定的元素。
**语法**:
```json
{"$pullAll": {"<arrayField>": [<value1>, <value2>, ...]}}
```
**示例**:
```json
{"$pullAll": {"tags": ["deprecated", "obsolete", "old"]}}
```
### $splice - 拼接数组
修改数组内容(类似 JavaScript 的 splice
**语法**:
```json
{"$splice": {"<arrayField>": [[start, deleteCount, ...items]]}}
```
**示例**:
```json
// 从索引 2 开始删除 1 个元素,插入 2 个新元素
{"$splice": {"items": [[2, 1, "new1", "new2"]]}}
```
---
## 算术更新操作符
### $inc - 递增
将字段的值增加指定的数量。
**语法**:
```json
{"$inc": {"<field>": <number>}}
```
**示例**:
```json
// 增加计数
{"$inc": {"viewCount": 1}}
// 减少数值
{"$inc": {"stock": -5}}
// 增加浮点数
{"$inc": {"balance": 100.50}}
```
### $mul - 乘法
将字段的值乘以指定的数量。
**语法**:
```json
{"$mul": {"<field>": <number>}}
```
**示例**:
```json
// 打 9 折
{"$mul": {"price": 0.9}}
// 增加 10%
{"$mul": {"quantity": 1.1}}
```
### $min - 最小值
只有当指定值小于当前值时才更新字段。
**语法**:
```json
{"$min": {"<field>": <value>}}
```
**示例**:
```json
// 更新最低价格
{"$min": {"lowPrice": 50}}
```
### $max - 最大值
只有当指定值大于当前值时才更新字段。
**语法**:
```json
{"$max": {"<field>": <value>}}
```
**示例**:
```json
// 更新最高分数
{"$max": {"highScore": 95}}
```
---
## 位运算更新操作符
### $bit - 位运算
对整数字段执行位运算。
**语法**:
```json
{"$bit": {"<field>": {<operation>: <value>}}}
```
**支持的运算**:
- `and`: 按位与
- `or`: 按位或
- `xor`: 按位异或
**示例**:
```json
// 按位与
{"$bit": {"flags": {"and": 15}}} // 保留低 4 位
// 按位或
{"$bit": {"permissions": {"or": 8}}} // 设置第 4 位
// 按位异或
{"$bit": {"status": {"xor": 1}}} // 切换第 1 位
```
---
## 条件更新操作符
### $ - 数组过滤器
更新数组中匹配的第一个元素。
**语法**:
```json
{"<arrayField>.<index>": <value>}
```
**示例**:
```json
// 更新数组第一个元素
{"$set": {"scores.0": 100}}
// 使用 $[identifier] 更新匹配的元素
{
"$set": {
"students.$[elem].grade": "A"
}
},
{
"arrayFilters": [
{"elem.name": "Alice"}
]
}
```
### $[] - 更新所有数组元素
更新数组中的所有元素。
**语法**:
```json
{"<arrayField>.$[]": <value>}
```
**示例**:
```json
// 更新所有数组元素
{"$set": {"scores.$[]": 0}}
```
### $[<identifier>] - 带过滤的数组更新
更新数组中匹配条件的元素。
**语法**:
```json
{"<arrayField>.$[<identifier>]": <value>}
```
**示例**:
```json
{
"$set": {
"students.$[s].grade": "A"
}
},
{
"arrayFilters": [
{"s.score": {"$gte": 90}}
]
}
```
---
## 使用示例
### 用户资料更新
```json
{
"$set": {
"name": "张三",
"email": "zhangsan@example.com"
},
"$inc": {
"loginCount": 1
},
"$currentDate": {
"lastLogin": true
}
}
```
### 购物车操作
```json
{
"$push": {
"items": {
"productId": "prod_001",
"quantity": 2,
"price": 99.99
}
},
"$inc": {
"totalAmount": 199.98
},
"$set": {
"updatedAt": ISODate("2024-01-01")
}
}
```
### 库存管理
```json
{
"$inc": {
"stock": -5,
"soldCount": 5
},
"$min": {
"lowStockAlert": 10
},
"$set": {
"lastSale": ISODate("2024-01-01")
}
}
```
### 评分系统
```json
{
"$push": {
"ratings": {
"userId": "user_001",
"score": 5,
"comment": "Excellent!"
}
},
"$inc": {
"ratingCount": 1,
"totalScore": 5
},
"$set": {
"averageRating": {"$divide": ["$totalScore", "$ratingCount"]}
}
}
```
### 标签管理
```json
{
"$addToSet": {
"tags": "new"
},
"$pull": {
"tags": "old"
},
"$push": {
"history": {
"$each": ["tag_updated"],
"$slice": -10
}
}
}
```
### 批量更新
```json
// 更新多个文档
{
"filter": {"department": "技术部"},
"update": {
"$inc": {"salary": 1000},
"$set": {"adjusted": true}
},
"multi": true
}
```
### Upsert 操作
```json
{
"filter": {"email": "user@example.com"},
"update": {
"$setOnInsert": {
"email": "user@example.com",
"createdAt": ISODate("2024-01-01")
},
"$set": {
"lastSeen": ISODate("2024-01-01")
},
"$inc": {
"visitCount": 1
}
},
"upsert": true
}
```
### 复杂数组操作
```json
{
"$push": {
"scores": {
"$each": [95, 87, 92],
"$sort": -1,
"$slice": 5,
"$position": 0
}
}
}
```
### 嵌套字段更新
```json
{
"$set": {
"address.street": "长安街",
"address.city": "北京",
"contact.phone": "123456789"
},
"$unset": {
"address.oldAddress": ""
}
}
```
---
## 最佳实践
### 1. 原子性保证
Gomog 的更新操作是原子的,可以安全地并发使用。
```json
// 安全的计数器递增
{"$inc": {"viewCount": 1}}
```
### 2. 使用 $setOnInsert 避免覆盖
```json
// ✅ 推荐:只在插入时设置创建时间
{
"$setOnInsert": {"createdAt": ISODate()},
"$set": {"updatedAt": ISODate()}
}
```
### 3. 合理使用数组修饰符
```json
// 限制数组大小,防止无限增长
{
"$push": {
"history": {
"$each": [newItem],
"$slice": -100 // 只保留最后 100 条
}
}
}
```
### 4. 使用 arrayFilters 精确更新
```json
// 精确定位要更新的数组元素
{
"$set": {"grades.$[g].grade": "A"},
"arrayFilters": [{"g.subject": "math"}]
}
```
### 5. 避免频繁更新大文档
```json
// ❌ 不推荐:每次更新整个文档
{"$set": {entireDocument}}
// ✅ 推荐:只更新变化的字段
{"$set": {"changedField": newValue}}
```
---
**维护者**: Gomog Team
**许可证**: MIT

724
manual/USER_GUIDE.md Normal file
View File

@ -0,0 +1,724 @@
# Gomog 用户手册
**版本**: v1.0.0-alpha
**最后更新**: 2026-03-14
**许可证**: MIT
---
## 📖 目录
1. [简介](#简介)
2. [快速开始](#快速开始)
3. [安装与配置](#安装与配置)
4. [基本使用](#基本使用)
5. [高级功能](#高级功能)
6. [最佳实践](#最佳实践)
7. [故障排查](#故障排查)
8. [常见问题](#常见问题)
---
## 简介
### 什么是 Gomog
Gomog 是一个兼容 MongoDB 风格 API 的内存查询引擎支持多数据库适配SQLite、PostgreSQL、达梦 DM8。它提供了丰富的聚合管道、查询操作符和更新操作符让你能够以熟悉的方式操作关系型数据库。
### 核心特性
- ✅ **MongoDB 风格 API**: 熟悉的查询语法,零学习成本
- ✅ **多数据库支持**: SQLite、PostgreSQL、达梦 DM8
- ✅ **完整的聚合管道**: 18+ 个聚合阶段50+ 个聚合表达式
- ✅ **丰富的查询操作符**: 16+ 个查询操作符
- ✅ **强大的更新操作符**: 17+ 个更新操作符
- ✅ **HTTP 和 TCP 双协议**: RESTful API 和 MongoDB 线协议支持
- ✅ **高性能**: 内存优化,并发安全
### 适用场景
- 快速原型开发
- 数据分析和报表
- 遗留系统现代化
- 多数据库统一访问层
- 教学和实验环境
---
## 快速开始
### 1. 下载与安装
```bash
# 从源码编译
git clone https://github.com/gomog/gomog.git
cd gomog
make build
# 或使用 Docker
docker pull gomog:latest
```
### 2. 配置文件
复制示例配置文件:
```bash
cp config.yaml.example config.yaml
```
编辑 `config.yaml`
```yaml
server:
http_addr: ":8080"
tcp_addr: ":27017"
mode: "dev"
database:
type: "sqlite"
dsn: "gomog.db"
max_open: 10
max_idle: 5
log:
level: "info"
format: "text"
```
### 3. 启动服务
```bash
# 直接运行
./bin/gomog -config config.yaml
# 或使用 make
make run
# Docker 运行
docker run -p 8080:8080 -p 27017:27017 gomog:latest
```
### 4. 验证安装
```bash
# HTTP 健康检查
curl http://localhost:8080/health
# 插入测试数据
curl -X POST http://localhost:8080/api/v1/testdb/users/insert \
-H "Content-Type: application/json" \
-d '{"documents": [{"name": "Alice", "age": 30}]}'
# 查询数据
curl -X POST http://localhost:8080/api/v1/testdb/users/find \
-H "Content-Type: application/json" \
-d '{"filter": {"age": {"$gt": 25}}}'
```
---
## 安装与配置
### 系统要求
- **操作系统**: Linux, macOS, Windows
- **Go 版本**: 1.21+
- **内存**: 最少 512MB推荐 1GB+
- **磁盘**: 最少 100MB 可用空间
### 安装方式
#### 方式一:源码编译(推荐)
```bash
# 克隆仓库
git clone https://github.com/gomog/gomog.git
cd gomog
# 编译
make build
# 验证
./bin/gomog --version
```
#### 方式二Docker
```bash
# 拉取镜像
docker pull gomog:latest
# 运行
docker run -d \
--name gomog \
-p 8080:8080 \
-p 27017:27017 \
-v $(pwd)/data:/data \
gomog:latest
```
#### 方式三:包管理器(待提供)
```bash
# Ubuntu/Debian
sudo apt install gomog
# CentOS/RHEL
sudo yum install gomog
# macOS (Homebrew)
brew install gomog
```
### 配置详解
#### 服务器配置
```yaml
server:
# HTTP 监听地址
# 格式:[host]:port
# 默认:":8080"
http_addr: ":8080"
# TCP 监听地址MongoDB 线协议)
# 格式:[host]:port
# 默认:":27017"
tcp_addr: ":27017"
# 运行模式
# 可选值dev, prod
# dev: 详细日志,调试信息
# prod: 精简日志,性能优化
mode: "dev"
```
#### 数据库配置
```yaml
database:
# 数据库类型
# 可选值sqlite, postgres, dm8
type: "sqlite"
# 数据源名称
# SQLite: 文件路径或 :memory:
# PostgreSQL: postgresql://user:pass@host:port/dbname?sslmode=disable
# DM8: dm://user:pass@host:port/dbname
dsn: "gomog.db"
# 最大打开连接数
# 默认10
max_open: 10
# 最大空闲连接数
# 默认5
max_idle: 5
# 连接最大生命周期(可选)
# 格式:时间 Duration 字符串
# 默认:"4h"
max_lifetime: "4h"
```
#### 日志配置
```yaml
log:
# 日志级别
# 可选值debug, info, warn, error
# debug: 所有日志
# info: 常规信息
# warn: 警告信息
# error: 错误信息
level: "info"
# 日志格式
# 可选值text, json
# text: 人类可读格式
# json: 结构化 JSON 格式
format: "text"
# 日志输出文件(可选)
# 默认stdout
output: "/var/log/gomog/gomog.log"
```
### 环境变量
Gomog 支持通过环境变量覆盖配置文件:
| 环境变量 | 配置项 | 示例 |
|---------|--------|------|
| `GOMOG_HTTP_ADDR` | server.http_addr | `GOMOG_HTTP_ADDR=:9000` |
| `GOMOG_TCP_ADDR` | server.tcp_addr | `GOMOG_TCP_ADDR=:27018` |
| `GOMOG_DB_TYPE` | database.type | `GOMOG_DB_TYPE=postgres` |
| `GOMOG_DB_DSN` | database.dsn | `GOMOG_DB_DSN=mydb.db` |
| `GOMOG_LOG_LEVEL` | log.level | `GOMOG_LOG_LEVEL=debug` |
---
## 基本使用
### 数据库和集合管理
#### 创建数据库
Gomog 会自动创建不存在的数据库,无需手动创建。
#### 创建集合
同样,集合会在首次插入数据时自动创建。
#### 列出所有数据库
```bash
curl -X POST http://localhost:8080/api/v1/admin/listDatabases
```
#### 列出所有集合
```bash
curl -X POST http://localhost:8080/api/v1/{database}/listCollections
```
### CRUD 操作
#### 插入Insert
```bash
# 单条插入
curl -X POST http://localhost:8080/api/v1/testdb/users/insert \
-H "Content-Type: application/json" \
-d '{"documents": [{"name": "Alice", "age": 30}]}'
# 批量插入
curl -X POST http://localhost:8080/api/v1/testdb/users/insert \
-H "Content-Type: application/json" \
-d '{
"documents": [
{"name": "Bob", "age": 25},
{"name": "Charlie", "age": 35}
]
}'
```
#### 查询Find
```bash
# 查询所有
curl -X POST http://localhost:8080/api/v1/testdb/users/find \
-H "Content-Type: application/json" \
-d '{}'
# 条件查询
curl -X POST http://localhost:8080/api/v1/testdb/users/find \
-H "Content-Type: application/json" \
-d '{"filter": {"age": {"$gt": 28}}}'
# 投影(选择字段)
curl -X POST http://localhost:8080/api/v1/testdb/users/find \
-H "Content-Type: application/json" \
-d '{
"filter": {"age": {"$gt": 28}},
"projection": {"name": 1, "age": 1}
}'
```
#### 更新Update
```bash
# 更新单个文档
curl -X POST http://localhost:8080/api/v1/testdb/users/update \
-H "Content-Type: application/json" \
-d '{
"filter": {"name": "Alice"},
"update": {"$set": {"age": 31}}
}'
# 更新多个文档
curl -X POST http://localhost:8080/api/v1/testdb/users/update \
-H "Content-Type: application/json" \
-d '{
"filter": {},
"update": {"$inc": {"age": 1}},
"multi": true
}'
# Upsert不存在则插入
curl -X POST http://localhost:8080/api/v1/testdb/users/update \
-H "Content-Type: application/json" \
-d '{
"filter": {"name": "David"},
"update": {"$setOnInsert": {"name": "David", "age": 28}},
"upsert": true
}'
```
#### 删除Delete
```bash
# 删除单个文档
curl -X POST http://localhost:8080/api/v1/testdb/users/delete \
-H "Content-Type: application/json" \
-d '{"filter": {"name": "Alice"}}'
# 删除多个文档
curl -X POST http://localhost:8080/api/v1/testdb/users/delete \
-H "Content-Type: application/json" \
-d '{"filter": {"age": {"$lt": 30}}, "multi": true}'
```
### 聚合操作
```bash
# 简单聚合
curl -X POST http://localhost:8080/api/v1/testdb/users/aggregate \
-H "Content-Type: application/json" \
-d '{
"pipeline": [
{"$match": {"age": {"$gte": 30}}},
{"$group": {
"_id": "$department",
"count": {"$sum": 1},
"avgAge": {"$avg": "$age"}
}}
]
}'
```
---
## 高级功能
### 聚合管道
Gomog 支持完整的 MongoDB 聚合管道,包括:
#### 1. 数据过滤
```json
{
"pipeline": [
{"$match": {"status": "active"}},
{"$limit": 10},
{"$skip": 5}
]
}
```
#### 2. 数据转换
```json
{
"pipeline": [
{"$addFields": {"fullName": {"$concat": ["$firstName", " ", "$lastName"]}}},
{"$project": {"_id": 0, "fullName": 1, "email": 1}}
]
}
```
#### 3. 数据分组
```json
{
"pipeline": [
{"$group": {
"_id": "$category",
"total": {"$sum": "$amount"},
"average": {"$avg": "$price"}
}}
]
}
```
#### 4. 数据排序
```json
{
"pipeline": [
{"$sort": {"created_at": -1}},
{"$limit": 10}
]
}
```
#### 5. 关联查询Lookup
```json
{
"pipeline": [
{"$lookup": {
"from": "orders",
"localField": "_id",
"foreignField": "userId",
"as": "orders"
}}
]
}
```
### 文本搜索
```bash
curl -X POST http://localhost:8080/api/v1/testdb/articles/aggregate \
-H "Content-Type: application/json" \
-d '{
"pipeline": [
{"$match": {"$text": {"$search": "database performance"}}},
{"$sort": {"score": {"$meta": "textScore"}}}
]
}'
```
### 窗口函数
```bash
curl -X POST http://localhost:8080/api/v1/testdb/sales/aggregate \
-H "Content-Type: application/json" \
-d '{
"pipeline": [{
"$setWindowFields": {
"partitionBy": "$region",
"sortBy": {"date": 1},
"output": {
"runningTotal": {
"$sum": "$amount",
"window": {"documents": ["unbounded", "current"]}
},
"rank": {"$documentNumber": {}}
}
}
}]
}'
```
### 递归查找
```bash
curl -X POST http://localhost:8080/api/v1/testdb/orgs/aggregate \
-H "Content-Type: application/json" \
-d '{
"pipeline": [{
"$graphLookup": {
"from": "orgs",
"startWith": "$parentId",
"connectFromField": "_id",
"connectToField": "parentId",
"as": "subOrgs",
"maxDepth": 5
}
}]
}'
```
---
## 最佳实践
### 性能优化
#### 1. 合理使用索引
```bash
# 为常用查询字段创建索引
curl -X POST http://localhost:8080/api/v1/testdb/users/createIndex \
-H "Content-Type: application/json" \
-d '{"keys": {"email": 1}, "unique": true}'
```
#### 2. 避免全表扫描
```bash
# ❌ 不推荐:全表扫描
{"filter": {"$expr": {"$gt": ["$age", 25]}}}
# ✅ 推荐:使用索引
{"filter": {"age": {"$gt": 25}}}
```
#### 3. 限制返回结果
```bash
# 总是使用 limit 限制返回数量
{"limit": 100}
```
#### 4. 使用投影减少数据传输
```bash
# 只返回需要的字段
{"projection": {"name": 1, "email": 1}}
```
### 数据安全
#### 1. 输入验证
始终在应用层验证用户输入,不要完全依赖数据库验证。
#### 2. 参数化查询
使用 Gomog 的参数化机制,避免注入攻击。
#### 3. 权限控制
在生产环境中使用数据库的权限控制机制。
### 监控与日志
#### 1. 启用慢查询日志
```yaml
log:
level: "debug"
slow_query_threshold: "100ms"
```
#### 2. 监控关键指标
- QPS每秒查询数
- 平均响应时间
- 错误率
- 连接池使用率
---
## 故障排查
### 常见问题
#### 1. 无法启动服务
**症状**: 启动时报错 "address already in use"
**解决**:
```bash
# 检查端口占用
lsof -i :8080
lsof -i :27017
# 修改配置文件使用其他端口
server:
http_addr: ":8081"
tcp_addr: ":27018"
```
#### 2. 数据库连接失败
**症状**: "failed to connect to database"
**解决**:
```bash
# 检查数据库配置
cat config.yaml | grep -A 5 database
# 验证数据库服务是否运行
# PostgreSQL
pg_isready -h localhost -p 5432
# SQLite
ls -la gomog.db
```
#### 3. 查询性能慢
**症状**: 查询响应时间超过预期
**解决**:
```bash
# 1. 查看执行计划
curl -X POST http://localhost:8080/api/v1/testdb/users/explain \
-H "Content-Type: application/json" \
-d '{"filter": {"age": {"$gt": 25}}}'
# 2. 添加索引
curl -X POST http://localhost:8080/api/v1/testdb/users/createIndex \
-H "Content-Type: application/json" \
-d '{"keys": {"age": 1}}'
# 3. 优化查询
# 避免使用 $expr改用原生操作符
```
#### 4. 内存不足
**症状**: OOM killer 杀死进程
**解决**:
```yaml
# 限制连接池大小
database:
max_open: 5
max_idle: 2
```
### 日志分析
#### 查看日志
```bash
# 实时查看日志
tail -f /var/log/gomog/gomog.log
# 搜索错误
grep "ERROR" /var/log/gomog/gomog.log
```
#### 日志级别说明
- **DEBUG**: 详细调试信息,包含所有查询和响应
- **INFO**: 常规运行信息
- **WARN**: 警告信息,不影响正常运行
- **ERROR**: 错误信息,需要关注
---
## 常见问题
### Q: Gomog 与 MongoDB 有什么区别?
A: Gomog 是一个兼容 MongoDB 风格 API 的查询引擎,底层可以使用 SQLite、PostgreSQL 等关系型数据库。它不是 MongoDB 的直接替代品,而是提供了一种熟悉的方式来操作关系型数据库。
### Q: 支持哪些 MongoDB 操作符?
A: Gomog 支持 16+ 个查询操作符、17+ 个更新操作符、18+ 个聚合阶段和 50+ 个聚合表达式。详见 [API 参考文档](API_REFERENCE.md)。
### Q: 如何在生产环境使用?
A:
1. 设置 `mode: "prod"`
2. 配置合适的连接池大小
3. 启用日志持久化
4. 配置监控告警
5. 定期备份数据
### Q: 是否支持事务?
A: 取决于底层数据库。PostgreSQL 和达梦 DM8 支持事务SQLite 支持有限的事务。
### Q: 如何备份数据?
A:
- **SQLite**: 直接复制 `.db` 文件
- **PostgreSQL**: 使用 `pg_dump`
- **DM8**: 使用 DM 的备份工具
### Q: 性能如何?
A: 对于中小规模数据集(<100 万条记录Gomog 能提供亚秒级的查询响应对于大规模数据建议使用原生数据库客户端以获得最佳性能
---
## 获取帮助
- **文档**: `/manual` 目录
- **示例**: [API_EXAMPLES.md](../doc/API_EXAMPLES.md)
- **问题反馈**: GitHub Issues
- **社区讨论**: GitHub Discussions
---
**维护者**: Gomog Team
**许可证**: MIT