MongoDB — 内嵌与执行计划
目标
在 Pod 内运行的真实 MongoDB 8.0 上插入、查询文档,创建索引,执行聚合, 设置 schema,并练习嵌入式建模。最后读取执行计划,并把其中的数字记录下来。
连接
mongosh labdb
使用 labdb。PostgreSQL 也在同一个 Pod 中运行,所以可以直接使用 psql——
把两个数据库并排放置,分别解决同一个问题,差异会清晰得多。
结果文件
有些步骤需要把结果保存到文件中。请先执行 mkdir -p /root/work/mongo。
在 shell 中保存 JSON 时,可以这样写:
mongosh --quiet labdb --eval 'JSON.stringify(db.items.find({},{_id:0}).toArray())' > /root/work/mongo/02-query.json
插入文档——值也可以是数组
使用 mongosh labdb 连接。通过 db.items.insertMany([...]) 插入至少 5 条记录。每个文档都要有 name(字符串)、qty(数字)和 tags(数组)。其中一个名称必须是 빨간 배낭。
items 中至少有 5 条记录;每个文档都有 name、qty 和 tags(数组)
只取需要的字段
查找 qty 大于 0 的文档,并且只投影 name 和 qty(_id: 0)。把结果以 JSON 数组保存到 /root/work/mongo/02-query.json。使用 mongosh --quiet --eval 和 JSON.stringify 会更方便。
02-query.json 包含 qty>0 的文档,并且每条只含 name 和 qty
创建索引并观察执行计划是否变化
执行 db.items.createIndex({name: 1})。然后运行 db.items.find({name:'빨간 배낭'}).explain(),确认计划中是否出现 IXSCAN。
存在 name 索引,并且该查询使用 IXSCAN
只修改一个字段
把 빨간 배낭 的 qty 改为 10。必须使用 $set——如果整体替换文档,未写出的字段会消失。
qty 为 10,并且 name 与 tags 保持不变
展开数组并按标签分组
用 $unwind 展开 tags,再用 $group 计算每个标签的 qty 总和。把结果保存到 /root/work/mongo/05-bytag.json,格式为 [{_id, total}, ...]。
05-bytag.json 中各标签的总和与实际数据一致
文档数据库也要设置 schema
使用 db.createCollection('orders', {validator: {$jsonSchema: {...}}}),把 qty 设为必填数字。规则只写下来却没有真正拦截,就等于不存在——请实际插入字符串,确认它会被拒绝。
orders 具有 $jsonSchema 验证,错误类型会被实际拒绝
一起读取的数据应嵌入保存
在 orders 中插入一条订单,把商品作为 lines 数组嵌入其中(至少 2 条,每项有 name 和 qty)。同时提供 qty,使其通过第 6 步的验证。可以用 db.orders.find({'lines.name': ...}) 查询数组内部。
一条订单文档中至少有 2 条 lines,并可通过 lines.name 查询
读取执行计划并记录数字
在 /root/work/mongo/08-explain.txt 中比较有索引时(IXSCAN)与无索引时(COLLSCAN)的结果。必须包含 explain('executionStats') 中 totalDocsExamined 等具体数字。
08-explain.txt 同时包含 IXSCAN、COLLSCAN 和数字