MongoDB模式

Mattakushi4322026-10-25查看 1335复制 1995

何时激活:MongoDB、mongoose、聚合管道、mongo、NoSQL、文档数据库、Atlas

Download (.md)

📘如何使用这个技能

  1. 1
    复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
  2. 2
    打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
  3. 3
    粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
  4. 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
来源:skillsdirectory

评论0

登录后参与评论

还没有评论,来抢沙发吧