docs(manual): 添加 Gomog 完整 API 和操作符文档
- 新增聚合管道参考文档 (AGGREGATION_PIPELINE.md),涵盖数据过滤、转换、分组等阶段 - 新增 HTTP API 参考文档 (HTTP_API.md),包含数据库管理、文档操作、查询等功能接口 - 新增查询操作符参考文档 (QUERY_OPERATORS.md),提供完整的比较、逻辑、数组等操作符说明 - 包含详细的 API 端点、请求参数、响应格式及使用示例 - 提供最佳实践和性能优化建议 - 覆盖从基础 CRUD 操作到复杂聚合管道的完整功能说明
This commit is contained in:
parent
e44ee72382
commit
7b38ec9877
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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*
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue