首页 / MongoDB 入门教程 / 内嵌文档查询

MongoDB 入门教程

内嵌文档查询

本教程共 50 篇 · 第 18 篇 · 更新于 2026-07-30 · 约 6 分钟阅读

MongoDBMongoDB 入门教程内嵌文档点号路径精确匹配嵌套查询

18. 内嵌文档查询

本节目标:学会用点号路径查询内嵌文档的子字段,理解整文档匹配的写法,并弄懂为什么整文档匹配对字段顺序那么挑剔。

在 MongoDB 里,一个字段的值可以又是一个完整文档。这种「文档套文档」的结构叫内嵌文档(Embedded Document)。我们的 products 集合里就有一个 location 字段,它存的是地理坐标点:

// 先建示例集合,后面所有查询都基于它
db.products.insertMany([
  { _id: 101, name: "机械键盘", price: 399, category: "外设",
    stock: 50, tags: ["热销", "机械"],
    location: { type: "Point", coordinates: [116.40, 39.90] } },
  { _id: 102, name: "无线鼠标", price: 129, category: "外设",
    stock: 120, tags: ["无线"],
    location: { type: "Point", coordinates: [121.47, 31.23] } },
  { _id: 103, name: "27寸显示器", price: 1099, category: "显示器",
    stock: 30, tags: ["4K"],
    location: { type: "Point", coordinates: [113.26, 23.13] } }
])

用点号路径匹配子字段

想查 location 里面的某个子字段,不能直接写 { location.type: "Point" } 这种语法——花括号会被当成别的东西。正确做法是用点号(dot notation)把外层字段和子字段连起来:

// 找出所有坐标类型为 Point 的商品
db.products.find({ "location.type": "Point" })

点号路径就是「外层字段.子字段」。注意字段名要用引号包起来,避免点号被当成小数。

Tip

点号路径可以一直往下挖。如果 location 里又套了一层 { type: { kind: "Point" } },就用 "location.type.kind" 去匹配。

整文档精确匹配

如果你想按整个内嵌文档来匹配,就把子文档原样写进查询条件:

// 找出坐标是北京那一支点的商品
db.products.find({
  location: { type: "Point", coordinates: [116.40, 39.90] }
})

这条会命中 _id: 101 那条,因为它整体长得一模一样。

整文档匹配对字段顺序敏感

这是新手最容易踩的坑。整文档匹配要求字段顺序、字段名、值都完全一致。把上面例子的顺序换一下就不匹配了:

// 顺序反了:coordinates 写在 type 前面,查不到任何东西
db.products.find({
  location: { coordinates: [116.40, 39.90], type: "Point" }
})
Warning

整文档匹配是「结构 + 顺序 + 值」三位一体的比较。只要字段顺序不同,即使内容一样也查不到。生产环境里字段顺序谁也说不准,所以整文档匹配要慎用。

点号路径 vs 整文档匹配,怎么选

我的经验是:绝大多数场景用点号路径。它只关心某个子字段的值,不管其他字段和顺序,稳健得多。

方式写法顺序敏感适用场景
点号路径{ "location.type": "Point" }只关心某个子字段
整文档{ location: { ... } }确认整段结构完全一致

点号路径也能加比较运算符

子字段一样可以配合比较运算符。比如只想看经度大于 120 的商品:

// coordinates 是数组,[0] 是经度
db.products.find({ "location.coordinates.0": { $gt: 120 } })

这里 "location.coordinates.0" 连用了两层点号,先下钻到 coordinates,再取下标第 0 个元素。

Note

数组下标也是通过点号访问的,写法像 "字段.0"。数组查询我们后面会专门讲,这里先混个眼熟。

学完这章,你已经能从容查询任意层级的内嵌文档了。下章我们聊一个更微妙的话题:怎么查「没有值」或「字段根本不存在」的文档。