From 7b38ec98779063d29dbbae331f889ac51645035f Mon Sep 17 00:00:00 2001 From: kingecg Date: Sat, 14 Mar 2026 19:46:35 +0800 Subject: [PATCH] =?UTF-8?q?docs(manual):=20=E6=B7=BB=E5=8A=A0=20Gomog=20?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=20API=20=E5=92=8C=E6=93=8D=E4=BD=9C=E7=AC=A6?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增聚合管道参考文档 (AGGREGATION_PIPELINE.md),涵盖数据过滤、转换、分组等阶段 - 新增 HTTP API 参考文档 (HTTP_API.md),包含数据库管理、文档操作、查询等功能接口 - 新增查询操作符参考文档 (QUERY_OPERATORS.md),提供完整的比较、逻辑、数组等操作符说明 - 包含详细的 API 端点、请求参数、响应格式及使用示例 - 提供最佳实践和性能优化建议 - 覆盖从基础 CRUD 操作到复杂聚合管道的完整功能说明 --- manual/AGGREGATION_PIPELINE.md | 807 ++++++++++++++++++++++++++++++ manual/HTTP_API.md | 867 +++++++++++++++++++++++++++++++++ manual/QUERY_OPERATORS.md | 549 +++++++++++++++++++++ manual/QUICK_REFERENCE.md | 277 +++++++++++ manual/README.md | 213 ++++++++ manual/TCP_PROTOCOL.md | 692 ++++++++++++++++++++++++++ manual/UPDATE_OPERATORS.md | 674 +++++++++++++++++++++++++ manual/USER_GUIDE.md | 724 +++++++++++++++++++++++++++ 8 files changed, 4803 insertions(+) create mode 100644 manual/AGGREGATION_PIPELINE.md create mode 100644 manual/HTTP_API.md create mode 100644 manual/QUERY_OPERATORS.md create mode 100644 manual/QUICK_REFERENCE.md create mode 100644 manual/README.md create mode 100644 manual/TCP_PROTOCOL.md create mode 100644 manual/UPDATE_OPERATORS.md create mode 100644 manual/USER_GUIDE.md diff --git a/manual/AGGREGATION_PIPELINE.md b/manual/AGGREGATION_PIPELINE.md new file mode 100644 index 0000000..52c21bc --- /dev/null +++ b/manual/AGGREGATION_PIPELINE.md @@ -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": {"": {"": }}} +``` + +**示例**: +```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": } +``` + +**示例**: +```json +{"$limit": 10} +``` + +### $skip + +跳过指定数量的文档。 + +**语法**: +```json +{"$skip": } +``` + +**示例**: +```json +{"$skip": 20} +``` + +### $sample + +随机采样文档。 + +**语法**: +```json +{"$sample": {"size": }} +``` + +**示例**: +```json +{"$sample": {"size": 5}} +``` + +### $bucket + +将文档分组到桶中。 + +**语法**: +```json +{ + "$bucket": { + "groupBy": "", + "boundaries": [, , ...], + "default": , + "output": {: {}, ...} + } +} +``` + +**示例**: +```json +{ + "$bucket": { + "groupBy": "$price", + "boundaries": [0, 100, 500, 1000], + "default": "Other", + "output": { + "count": {"$sum": 1}, + "avgPrice": {"$avg": "$price"} + } + } +} +``` + +--- + +## 数据转换阶段 + +### $project + +重塑文档结构(选择字段、添加计算字段等)。 + +**语法**: +```json +{ + "$project": { + "": , + "": , + ... + } +} +``` + +**示例**: +```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": { + "": + } +} +``` + +**示例**: +```json +{ + "$addFields": { + "total": {"$add": ["$price", "$tax"]}, + "discountedPrice": {"$multiply": ["$price", 0.9]} + } +} +``` + +### $unset / $unset + +移除字段。 + +**语法**: +```json +{"$unset": ""} +// 或 +{"$unset": ["", "", ...]} +``` + +**示例**: +```json +{"$unset": ["tempField", "internalData"]} +``` + +### $replaceRoot / $replaceWith + +替换根文档。 + +**语法**: +```json +{"$replaceRoot": {"newRoot": }} +``` + +**示例**: +```json +{ + "$replaceRoot": {"newRoot": "$user"} +} +``` + +--- + +## 数据分组阶段 + +### $group + +按指定键分组并计算聚合值。 + +**语法**: +```json +{ + "$group": { + "_id": , + "": {}, + "": {}, + ... + } +} +``` + +**示例**: +```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": {"": , "": , ...}} +``` + +**示例**: +```json +{ + "$sort": { + "createdAt": -1, // 降序 + "name": 1 // 升序 + } +} +``` + +### $sortByCount + +按值分组并计数。 + +**语法**: +```json +{"$sortByCount": } +``` + +**示例**: +```json +{"$sortByCount": "$category"} +``` + +等价于: +```json +[ + {"$group": {"_id": "$category", "count": {"$sum": 1}}}, + {"$sort": {"count": -1}} +] +``` + +--- + +## 关联查询阶段 + +### $lookup + +左外连接其他集合。 + +**语法 1** (基本形式): +```json +{ + "$lookup": { + "from": "", + "localField": "", + "foreignField": "", + "as": "" + } +} +``` + +**示例 1**: +```json +{ + "$lookup": { + "from": "orders", + "localField": "_id", + "foreignField": "userId", + "as": "orders" + } +} +``` + +**语法 2** (高级形式,支持管道): +```json +{ + "$lookup": { + "from": "", + "let": {: , ...}, + "pipeline": [], + "as": "" + } +} +``` + +**示例 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": "", + "startWith": , + "connectFromField": "", + "connectToField": "", + "as": "", + "maxDepth": , + "depthField": "", + "restrictSearchWithMatch": + } +} +``` + +**示例**: +```json +{ + "$graphLookup": { + "from": "orgs", + "startWith": "$parentId", + "connectFromField": "_id", + "connectToField": "parentId", + "as": "subOrgs", + "maxDepth": 5, + "depthField": "level" + } +} +``` + +--- + +## 性能优化阶段 + +### $facet + +多面聚合(并行执行多个子管道)。 + +**语法**: +```json +{ + "$facet": { + "": [], + "": [], + ... + } +} +``` + +**示例**: +```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": , + "sortBy": {: , ...}, + "output": { + "": { + "": {}, + "window": { + "documents": [, ] + } + }, + ... + } + } +} +``` + +**示例**: +```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 diff --git a/manual/HTTP_API.md b/manual/HTTP_API.md new file mode 100644 index 0000000..a07c0a5 --- /dev/null +++ b/manual/HTTP_API.md @@ -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 diff --git a/manual/QUERY_OPERATORS.md b/manual/QUERY_OPERATORS.md new file mode 100644 index 0000000..2a7df97 --- /dev/null +++ b/manual/QUERY_OPERATORS.md @@ -0,0 +1,549 @@ +# Gomog 查询操作符参考文档 + +**版本**: v1.0.0-alpha +**最后更新**: 2026-03-14 + +--- + +## 📖 目录 + +1. [比较操作符](#比较操作符) +2. [逻辑操作符](#逻辑操作符) +3. [元素操作符](#元素操作符) +4. [数组操作符](#数组操作符) +5. [正则表达式操作符](#正则表达式操作符) +6. [位运算操作符](#位运算操作符) +7. [使用示例](#使用示例) + +--- + +## 比较操作符 + +### $eq - 等于 + +匹配等于指定值的文档。 + +**语法**: +```json +{"field": {"$eq": }} +// 或简写 +{"field": } +``` + +**示例**: +```json +{"age": {"$eq": 30}} +// 等价于 +{"age": 30} +``` + +### $ne - 不等于 + +匹配不等于指定值的文档。 + +**语法**: +```json +{"field": {"$ne": }} +``` + +**示例**: +```json +{"status": {"$ne": "inactive"}} +``` + +### $gt - 大于 + +匹配大于指定值的文档。 + +**语法**: +```json +{"field": {"$gt": }} +``` + +**示例**: +```json +{"price": {"$gt": 100}} +``` + +### $gte - 大于等于 + +匹配大于或等于指定值的文档。 + +**语法**: +```json +{"field": {"$gte": }} +``` + +**示例**: +```json +{"age": {"$gte": 18}} +``` + +### $lt - 小于 + +匹配小于指定值的文档。 + +**语法**: +```json +{"field": {"$lt": }} +``` + +**示例**: +```json +{"score": {"$lt": 60}} +``` + +### $lte - 小于等于 + +匹配小于或等于指定值的文档。 + +**语法**: +```json +{"field": {"$lte": }} +``` + +**示例**: +```json +{"quantity": {"$lte": 10}} +``` + +### $in - 在数组中 + +匹配值在指定数组中的文档。 + +**语法**: +```json +{"field": {"$in": [, , ...]}} +``` + +**示例**: +```json +{"status": {"$in": ["active", "pending"]}} +{"age": {"$in": [18, 25, 30]}} +``` + +### $nin - 不在数组中 + +匹配值不在指定数组中的文档。 + +**语法**: +```json +{"field": {"$nin": [, , ...]}} +``` + +**示例**: +```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": {}}} +``` + +**示例**: +```json +{"price": {"$not": {"$gt": 100}}} +``` + +### $nor - 或非 + +匹配所有条件都不满足的文档。 + +**语法**: +```json +{"$nor": [{"condition1"}, {"condition2"}, ...]} +``` + +**示例**: +```json +{ + "$nor": [ + {"status": "draft"}, + {"archived": true} + ] +} +``` + +--- + +## 元素操作符 + +### $exists - 字段存在 + +匹配包含或不包含指定字段的文档。 + +**语法**: +```json +{"field": {"$exists": }} +``` + +**示例**: +```json +// 包含 email 字段的文档 +{"email": {"$exists": true}} + +// 不包含 phone 字段的文档 +{"phone": {"$exists": false}} +``` + +### $type - 类型检查 + +匹配字段类型等于指定类型的文档。 + +**语法**: +```json +{"field": {"$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": [, , ...]}} +``` + +**示例**: +```json +{"tags": {"$all": ["mongodb", "database", "nosql"]}} +``` + +### $elemMatch - 元素匹配 + +匹配数组中至少有一个元素满足条件的文档。 + +**语法**: +```json +{"field": {"$elemMatch": {}}} +``` + +**示例**: +```json +// 数组中有元素大于 80 +{"scores": {"$elemMatch": {"$gt": 80}}} + +// 数组中有对象满足多个条件 +{"results": {"$elemMatch": { + "product": "laptop", + "price": {"$lt": 1000} +}}} +``` + +### $size - 数组大小 + +匹配数组长度等于指定值的文档。 + +**语法**: +```json +{"field": {"$size": }} +``` + +**示例**: +```json +{"tags": {"$size": 3}} +``` + +--- + +## 正则表达式操作符 + +### $regex - 正则匹配 + +使用正则表达式匹配字符串。 + +**语法**: +```json +{"field": {"$regex": , "$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": }} +``` + +**示例**: +```json +{"flags": {"$bitsAllClear": 8}} // 第 4 位为 0 +``` + +### $bitsAllSet - 所有指定位为 1 + +匹配所有指定位都为 1 的文档。 + +**语法**: +```json +{"field": {"$bitsAllSet": }} +``` + +**示例**: +```json +{"permissions": {"$bitsAllSet": 7}} // 第 1-3 位都为 1 +``` + +### $bitsAnyClear - 任意指定位为 0 + +匹配任意指定位为 0 的文档。 + +**语法**: +```json +{"field": {"$bitsAnyClear": }} +``` + +**示例**: +```json +{"status": {"$bitsAnyClear": 15}} +``` + +### $bitsAnySet - 任意指定位为 1 + +匹配任意指定位为 1 的文档。 + +**语法**: +```json +{"field": {"$bitsAnySet": }} +``` + +**示例**: +```json +{"flags": {"$bitsAnySet": 1}} // 第 1 位为 1 +``` + +--- + +## 特殊操作符 + +### $expr - 表达式 + +允许在查询中使用聚合表达式。 + +**语法**: +```json +{"$expr": {}} +``` + +**示例**: +```json +// 比较两个字段 +{"$expr": {"$gt": ["$salary", "$expenses"]}} + +// 复杂计算 +{"$expr": {"$lt": [{"$multiply": ["$price", "$quantity"]}, 100]}} +``` + +### $jsonSchema - JSON Schema 验证 + +使用 JSON Schema 验证文档。 + +**语法**: +```json +{"$jsonSchema": {}} +``` + +**示例**: +```json +{ + "$jsonSchema": { + "bsonType": "object", + "required": ["name", "age"], + "properties": { + "name": {"bsonType": "string"}, + "age": {"bsonType": "int", "minimum": 0} + } + } +} +``` + +### $mod - 模运算 + +匹配除以指定数的余数。 + +**语法**: +```json +{"field": {"$mod": [, ]}} +``` + +**示例**: +```json +// 偶数 +{"count": {"$mod": [2, 0]}} + +// 除以 5 余 3 +{"number": {"$mod": [5, 3]}} +``` + +### $where - JavaScript 表达式 + +使用 JavaScript 表达式进行匹配(性能较低)。 + +**语法**: +```json +{"$where": ""} +``` + +**示例**: +```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 diff --git a/manual/QUICK_REFERENCE.md b/manual/QUICK_REFERENCE.md new file mode 100644 index 0000000..84214dc --- /dev/null +++ b/manual/QUICK_REFERENCE.md @@ -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 diff --git a/manual/README.md b/manual/README.md new file mode 100644 index 0000000..2448786 --- /dev/null +++ b/manual/README.md @@ -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* diff --git a/manual/TCP_PROTOCOL.md b/manual/TCP_PROTOCOL.md new file mode 100644 index 0000000..2af8930 --- /dev/null +++ b/manual/TCP_PROTOCOL.md @@ -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 diff --git a/manual/UPDATE_OPERATORS.md b/manual/UPDATE_OPERATORS.md new file mode 100644 index 0000000..1073e71 --- /dev/null +++ b/manual/UPDATE_OPERATORS.md @@ -0,0 +1,674 @@ +# Gomog 更新操作符参考文档 + +**版本**: v1.0.0-alpha +**最后更新**: 2026-03-14 + +--- + +## 📖 目录 + +1. [字段更新操作符](#字段更新操作符) +2. [数组更新操作符](#数组更新操作符) +3. [算术更新操作符](#算术更新操作符) +4. [位运算更新操作符](#位运算更新操作符) +5. [条件更新操作符](#条件更新操作符) +6. [使用示例](#使用示例) + +--- + +## 字段更新操作符 + +### $set - 设置字段 + +设置字段的值。如果字段不存在,则创建该字段。 + +**语法**: +```json +{"$set": {"": }} +``` + +**示例**: +```json +// 设置单个字段 +{"$set": {"status": "active"}} + +// 设置多个字段 +{ + "$set": { + "status": "active", + "lastModified": ISODate("2024-01-01") + } +} + +// 设置嵌套字段 +{"$set": {"address.city": "Beijing"}} +``` + +### $unset - 移除字段 + +移除一个或多个字段。 + +**语法**: +```json +{"$unset": {"": ""}} +// 或 +{"$unset": {"": "", "": ""}} +``` + +**示例**: +```json +// 移除单个字段 +{"$unset": {"tempField": ""}} + +// 移除多个字段 +{ + "$unset": { + "oldField": "", + "deprecated": "" + } +} +``` + +### $setOnInsert - 仅在插入时设置 + +仅在 upsert 操作创建新文档时设置字段。 + +**语法**: +```json +{"$setOnInsert": {"": }} +``` + +**示例**: +```json +{ + "$setOnInsert": { + "createdAt": ISODate("2024-01-01"), + "createdBy": "system" + } +} +``` + +### $rename - 重命名字段 + +重命名字段名。 + +**语法**: +```json +{"$rename": {"": ""}} +``` + +**示例**: +```json +// 重命名单个字段 +{"$rename": {"oldName": "newName"}} + +// 重命名多个字段 +{ + "$rename": { + "firstName": "givenName", + "lastName": "familyName" + } +} +``` + +### $currentDate - 设置为当前时间 + +将字段设置为当前日期或时间戳。 + +**语法**: +```json +{"$currentDate": {"": }} +``` + +**类型**: +- `true`: BSON Date (默认) +- `{$type: "timestamp"}`: BSON Timestamp + +**示例**: +```json +// 设置为 Date +{"$currentDate": {"lastModified": true}} + +// 设置为 Timestamp +{"$currentDate": {"lastModified": {$type: "timestamp"}}} +``` + +--- + +## 数组更新操作符 + +### $push - 推入元素 + +向数组中添加一个元素。 + +**语法**: +```json +{"$push": {"": }} +``` + +**示例**: +```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": {"": }} +``` + +**示例**: +```json +// 添加唯一值 +{"$addToSet": {"tags": "database"}} + +// 配合 $each 使用 +{ + "$addToSet": { + "tags": { + "$each": ["mongodb", "nosql", "database"] + } + } +} +``` + +### $pop - 弹出元素 + +从数组中移除第一个或最后一个元素。 + +**语法**: +```json +{"$pop": {"": }} +``` + +**方向**: +- `1`: 移除最后一个元素 +- `-1`: 移除第一个元素 + +**示例**: +```json +// 移除最后一个元素 +{"$pop": {"items": 1}} + +// 移除第一个元素 +{"$pop": {"items": -1}} +``` + +### $pull - 拉出元素 + +从数组中移除所有匹配的元素。 + +**语法**: +```json +{"$pull": {"": {}}} +``` + +**示例**: +```json +// 移除等于特定值的元素 +{"$pull": {"tags": "deprecated"}} + +// 移除满足条件的元素 +{"$pull": { + "items": { + "price": {"$lt": 100} + } +}} + +// 移除数组中的对象 +{"$pull": { + "users": { + "status": "inactive" + } +}} +``` + +### $pullAll - 拉出多个元素 + +从数组中移除多个指定的元素。 + +**语法**: +```json +{"$pullAll": {"": [, , ...]}} +``` + +**示例**: +```json +{"$pullAll": {"tags": ["deprecated", "obsolete", "old"]}} +``` + +### $splice - 拼接数组 + +修改数组内容(类似 JavaScript 的 splice)。 + +**语法**: +```json +{"$splice": {"": [[start, deleteCount, ...items]]}} +``` + +**示例**: +```json +// 从索引 2 开始删除 1 个元素,插入 2 个新元素 +{"$splice": {"items": [[2, 1, "new1", "new2"]]}} +``` + +--- + +## 算术更新操作符 + +### $inc - 递增 + +将字段的值增加指定的数量。 + +**语法**: +```json +{"$inc": {"": }} +``` + +**示例**: +```json +// 增加计数 +{"$inc": {"viewCount": 1}} + +// 减少数值 +{"$inc": {"stock": -5}} + +// 增加浮点数 +{"$inc": {"balance": 100.50}} +``` + +### $mul - 乘法 + +将字段的值乘以指定的数量。 + +**语法**: +```json +{"$mul": {"": }} +``` + +**示例**: +```json +// 打 9 折 +{"$mul": {"price": 0.9}} + +// 增加 10% +{"$mul": {"quantity": 1.1}} +``` + +### $min - 最小值 + +只有当指定值小于当前值时才更新字段。 + +**语法**: +```json +{"$min": {"": }} +``` + +**示例**: +```json +// 更新最低价格 +{"$min": {"lowPrice": 50}} +``` + +### $max - 最大值 + +只有当指定值大于当前值时才更新字段。 + +**语法**: +```json +{"$max": {"": }} +``` + +**示例**: +```json +// 更新最高分数 +{"$max": {"highScore": 95}} +``` + +--- + +## 位运算更新操作符 + +### $bit - 位运算 + +对整数字段执行位运算。 + +**语法**: +```json +{"$bit": {"": {: }}} +``` + +**支持的运算**: +- `and`: 按位与 +- `or`: 按位或 +- `xor`: 按位异或 + +**示例**: +```json +// 按位与 +{"$bit": {"flags": {"and": 15}}} // 保留低 4 位 + +// 按位或 +{"$bit": {"permissions": {"or": 8}}} // 设置第 4 位 + +// 按位异或 +{"$bit": {"status": {"xor": 1}}} // 切换第 1 位 +``` + +--- + +## 条件更新操作符 + +### $ - 数组过滤器 + +更新数组中匹配的第一个元素。 + +**语法**: +```json +{".": } +``` + +**示例**: +```json +// 更新数组第一个元素 +{"$set": {"scores.0": 100}} + +// 使用 $[identifier] 更新匹配的元素 +{ + "$set": { + "students.$[elem].grade": "A" + } +}, +{ + "arrayFilters": [ + {"elem.name": "Alice"} + ] +} +``` + +### $[] - 更新所有数组元素 + +更新数组中的所有元素。 + +**语法**: +```json +{".$[]": } +``` + +**示例**: +```json +// 更新所有数组元素 +{"$set": {"scores.$[]": 0}} +``` + +### $[] - 带过滤的数组更新 + +更新数组中匹配条件的元素。 + +**语法**: +```json +{".$[]": } +``` + +**示例**: +```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 diff --git a/manual/USER_GUIDE.md b/manual/USER_GUIDE.md new file mode 100644 index 0000000..0f965ea --- /dev/null +++ b/manual/USER_GUIDE.md @@ -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