MongoDB模式
Mattakushi4322026-10-25查看 1335复制 1995
何时激活:MongoDB、mongoose、聚合管道、mongo、NoSQL、文档数据库、Atlas
📘如何使用这个技能
- 1复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
- 2打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
- 3粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
- 4直接提出你的需求·AI 会按技能定义的工作流、格式和约束来处理,无需再解释背景
💡 提示:技能生效后,每次对话只需一句需求,AI 会按 SKILL.md 的流程执行。
SKILL.md4358 chars
---
name: mongodb-patterns
description: "When to activate: MongoDB, mongoose, aggregation pipeline, mongo, NoSQL, document database, Atlas"
origin: zakr
metadata:
namespace: zakr/devtools-pack
version: 1.0.0
category: databases
language: sql
platforms: [claude-code, codex, gemini-cli, cursor, aider, windsurf]
---
# MongoDB Patterns
## Aggregation Pipeline
```javascript
// Sales report: group by month, filter, sort
db.orders.aggregate([
{ $match: { status: "completed", createdAt: { $gte: new Date("2024-01-01") } } },
{ $group: {
_id: { $dateToString: { format: "%Y-%m", date: "$createdAt" } },
total: { $sum: "$amount" },
count: { $sum: 1 },
avg: { $avg: "$amount" }
}},
{ $sort: { _id: -1 } },
{ $limit: 12 }
]);
// $lookup (left join)
db.orders.aggregate([
{ $lookup: {
from: "users",
localField: "userId",
foreignField: "_id",
as: "user"
}},
{ $unwind: "$user" },
{ $project: { amount: 1, "user.name": 1, "user.email": 1 } }
]);
// $facet — multiple aggregations in one pass
db.products.aggregate([
{ $facet: {
byCategory: [
{ $group: { _id: "$category", count: { $sum: 1 } } }
],
priceStats: [
{ $group: { _id: null, min: { $min: "$price" }, max: { $max: "$price" } } }
],
total: [{ $count: "n" }]
}}
]);
```
## Indexes
```javascript
// Single field
db.users.createIndex({ email: 1 }, { unique: true });
// Compound — order matters (equality → sort → range)
db.orders.createIndex({ userId: 1, status: 1, createdAt: -1 });
// Partial index
db.orders.createIndex({ userId: 1 }, { partialFilterExpression: { status: "pending" } });
// TTL — auto-expire documents
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 86400 });
// Text search
db.articles.createIndex({ title: "text", body: "text" }, { weights: { title: 10 } });
db.articles.find({ $text: { $search: "mongodb patterns" } },
{ score: { $meta: "textScore" } })
.sort({ score: { $meta: "textScore" } });
// Check index usage
db.orders.explain("executionStats").find({ userId: ObjectId("...") });
```
## Schema Design Patterns
```javascript
// Embed (1-to-few, read together)
{
_id: ObjectId("..."),
name: "Alice",
addresses: [
{ type: "home", street: "123 Main St", city: "NYC" }
]
}
// Reference (1-to-many, independent access)
// order document
{ _id: ObjectId("..."), userId: ObjectId("..."), items: [...] }
// user document
{ _id: ObjectId("..."), name: "Alice" }
// Bucket pattern (time-series)
{
sensorId: "temp-01",
hour: ISODate("2024-01-15T12:00:00Z"),
readings: [22.1, 22.3, 22.0, ...], // up to 60 readings
count: 60,
min: 21.8, max: 22.5, avg: 22.1
}
// Outlier pattern — handle large arrays
{
_id: ObjectId("..."),
productId: ObjectId("..."),
reviews: [...], // first 1000
hasMore: true // flag for overflow documents
}
```
## Transactions (Multi-document)
```javascript
const session = client.startSession();
try {
await session.withTransaction(async () => {
await db.accounts.updateOne(
{ _id: fromId },
{ $inc: { balance: -amount } },
{ session }
);
await db.accounts.updateOne(
{ _id: toId },
{ $inc: { balance: amount } },
{ session }
);
});
} finally {
await session.endSession();
}
```
## Change Streams
```javascript
// Watch collection changes
const stream = db.orders.watch([
{ $match: { "fullDocument.status": "completed" } }
], { fullDocument: "updateLookup" });
stream.on("change", async (change) => {
console.log(change.operationType, change.fullDocument);
await notifyFulfillment(change.fullDocument);
});
// Resume after restart
const token = await redis.get("resume_token");
const stream = db.orders.watch([], { resumeAfter: token });
stream.on("change", async (change) => {
await redis.set("resume_token", JSON.stringify(change._id));
process(change);
});
```
## Performance Tips
- Analyze queries: `db.collection.explain("executionStats")`
- Index selectivity: avoid low-cardinality fields as leading index key
- Projection always — never fetch full document when a subset suffices
- Use `allowDiskUse: true` for large aggregations
- Atlas Search for full-text (Lucene-backed, much faster than `$text`)
- Increase `wiredTigerCacheSizeGB` to 50–60% of RAM