Use Cases (更新: 2026/6/1)

用 Claude Code 设计 NoSQL/MongoDB:Schema、索引与聚合实战

从访问模式出发,用 Claude Code 完成 MongoDB 建模、校验、索引、聚合、测试和上线检查。

用 Claude Code 设计 NoSQL/MongoDB:Schema、索引与聚合实战

先理解 MongoDB 的设计起点

NoSQL/MongoDB 不是把数据强行放进固定的行和列,而是按接近 JSON 的文档保存数据的数据库。因此,MongoDB 的重点不是先画出很多表,而是先确认应用会怎样读取、写入、过滤和汇总这些文档。

使用 Claude Code 时,不要只说“帮我建 users、products、orders 三个 collection”。更有效的做法是把页面、API 响应、更新频率、数据规模、报表需求和权限边界说清楚。这样 Claude Code 才能判断什么时候 embedding,什么时候 reference,哪些索引真正对应查询,聚合管道是否会变重,以及上线前应该怎样测试。

三个以上真实场景

场景常见读取方式推荐模型主要风险
电商订单用户订单列表、订单详情、月度销售额在订单里嵌入购买时的商品名、价格、分类,同时保留 productId商品改价后错误改写历史订单
SaaS 审计日志按组织、用户、日期和事件查询追加型文档,配合复合索引和必要的 TTL大集合全表扫描
内容管理系统通过 slug 取文章,按状态和分类列出明确 slugstatus、发布时间索引草稿或内部备注泄露
客服工单客户队列、负责人队列、最近评论有上限的评论可嵌入,附件和长文本分离数组无限增长

如果你还在比较 MongoDB、SQL 和 ORM 的边界,可以一起参考 Claude Code 数据库设计API 开发Prisma ORMSQL 优化

推荐给 Claude Code 的提示词

你是 MongoDB 设计评审。
请先从访问模式出发,而不是先从 collection 名称出发。

需求:
- 用户按时间倒序查看自己的订单列表
- 订单详情显示购买时的商品名、价格和分类
- 商品主数据改价不能影响历史订单
- 管理后台需要按月份、状态、商品分类统计收入
- 只有在部分成功会破坏业务一致性时才使用 transaction
- 输出 validation schema、索引、seed 数据、aggregation、explain 检查和上线 checklist

回答里必须写清楚哪些字段是嵌入,哪些字段是引用。订单里的商品名、购买价格、购买时分类属于订单事实,通常应该嵌入。商品库存、当前描述、商品页展示信息则属于商品主数据,用 productId 引用更合适。

可直接运行的最小示例

先启动 MongoDB:

docker run --name mongo-claude-demo -p 27017:27017 -d mongo:8

安装官方 Node.js Driver:

npm init -y
npm install mongodb
npm install -D tsx typescript
mkdir -p src

创建 src/mongodb-workflow.ts

import { MongoClient, ObjectId } from "mongodb";

const client = new MongoClient(process.env.MONGODB_URI ?? "mongodb://localhost:27017");

async function main() {
  await client.connect();
  const db = client.db("claude_code_shop_zh");
  await db.dropDatabase();

  await db.createCollection("orders", {
    validator: {
      $jsonSchema: {
        bsonType: "object",
        required: ["userId", "status", "items", "totalAmount", "createdAt", "updatedAt"],
        properties: {
          userId: { bsonType: "objectId" },
          status: { enum: ["pending", "paid", "shipped", "cancelled"] },
          totalAmount: { bsonType: ["int", "long", "double", "decimal"], minimum: 0 },
          createdAt: { bsonType: "date" },
          updatedAt: { bsonType: "date" },
          items: {
            bsonType: "array",
            minItems: 1,
            items: {
              bsonType: "object",
              required: ["productId", "name", "category", "price", "quantity"],
              properties: {
                productId: { bsonType: "objectId" },
                name: { bsonType: "string" },
                category: { bsonType: "string" },
                price: { bsonType: ["int", "long", "double", "decimal"], minimum: 0 },
                quantity: { bsonType: "int", minimum: 1 }
              }
            }
          }
        }
      }
    }
  });

  const products = db.collection("products");
  const orders = db.collection("orders");

  await Promise.all([
    orders.createIndex({ userId: 1, createdAt: -1 }, { name: "orders_by_user_recent" }),
    orders.createIndex({ status: 1, createdAt: -1 }, { name: "orders_by_status_recent" }),
    orders.createIndex({ "items.category": 1, createdAt: -1 }, { name: "orders_by_category_month" })
  ]);

  const inserted = await products.insertMany([
    { name: "Claude Code Workshop", category: "training", currentPrice: 48000 },
    { name: "MongoDB Review Template", category: "template", currentPrice: 9800 }
  ]);

  const userId = new ObjectId();
  const now = new Date("2026-06-01T09:00:00.000Z");

  await orders.insertOne({
    userId,
    status: "paid",
    items: [
      { productId: inserted.insertedIds[0], name: "Claude Code Workshop", category: "training", price: 48000, quantity: 1 },
      { productId: inserted.insertedIds[1], name: "MongoDB Review Template", category: "template", price: 9800, quantity: 2 }
    ],
    totalAmount: 67600,
    createdAt: now,
    updatedAt: now
  });

  const report = await orders.aggregate([
    { $match: { status: { $in: ["paid", "shipped"] } } },
    { $unwind: "$items" },
    {
      $group: {
        _id: {
          month: { $dateToString: { format: "%Y-%m", date: "$createdAt" } },
          category: "$items.category"
        },
        revenue: { $sum: { $multiply: ["$items.price", "$items.quantity"] } },
        quantity: { $sum: "$items.quantity" }
      }
    },
    { $sort: { "_id.month": 1, revenue: -1 } }
  ]).toArray();

  const explain = await orders.find({ userId }).sort({ createdAt: -1 }).limit(10).explain("executionStats");
  if (report.length !== 2) throw new Error("aggregation failed");
  if ((explain.executionStats?.totalDocsExamined ?? 0) > 1) throw new Error("index check failed");

  console.log(JSON.stringify({ report, examined: explain.executionStats.totalDocsExamined }, null, 2));
}

main()
  .catch((error) => {
    console.error(error);
    process.exitCode = 1;
  })
  .finally(async () => {
    await client.close();
  });

执行:

npx tsx src/mongodb-workflow.ts

这个示例同时覆盖 validation schema、索引、seed、aggregation pipeline 和 explain 检查。把输出交给 Claude Code 复盘,可以让它判断索引顺序是否匹配查询和排序。

embedding 与 reference 的判断

如果数据经常一起读取,并且代表某个时间点的事实,就适合 embedding。订单里的购买时价格就是典型例子。如果数据会独立更新、会无限增长,或者必须只有一个真实来源,就更适合 reference。不要把审计日志塞进账户文档,也不要把无限评论数组一直写进同一个工单。

这种重复不是偷懒,而是为了读性能做的有意非规范化。关键是把理由写进设计文档。

索引、聚合与 transaction

索引要从查询倒推。find({ userId }).sort({ createdAt: -1 }) 对应 { userId: 1, createdAt: -1 }。聚合管道应尽量先 $match 缩小范围,再 $unwind,最后 $group$sort。高频后台报表可以考虑缓存或预聚合集合,不一定每次页面访问都实时计算。

transaction 只放在业务上不能部分成功的边界,例如“订单改为 paid”和“写入支付记录”必须一起成功。通知、搜索索引同步、浏览量统计通常可以异步重试。

官方资料建议直接看 Data ModelingIndexesAggregationTransactionsMongoDB Node.js Driver

常见坑

第一个坑是把关系型数据库的范式照搬过来,导致每个订单详情都要在应用层做多次查询。第二个坑是过度嵌入,让评论、日志、通知这种会增长的数据撑大父文档。第三个坑是只依赖 TypeScript 类型,不在数据库层做校验。第四个坑是创建了索引却不看 explain("executionStats")。第五个坑是把重型 aggregation 放在每个 API 请求里。

上线前请确认:核心查询都有索引,validation schema 已应用,seed 覆盖列表、详情、报表和异常数据,explain 没有意外全扫描,transaction 边界已写清楚,回滚和备份方案可执行。

如果团队需要把这些步骤变成可复用流程,ClaudeCodeLab 可以提供 Claude Code 培训、CLAUDE.md 模板和 MongoDB/API 设计咨询。这个工作流实际使用后,最有价值的不是多加索引,而是让 Claude Code 基于 explain 结果指出哪些查询形状应该先调整。

#Claude Code #MongoDB #NoSQL #数据库 #后端
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。