HOWTO · MongoDB
MongoDB 嵌套字段投影
本教程介绍如何使用点表示法和 find() 选择 MongoDB 嵌套字段、使用 $project 调整聚合结果结构,以及使用 $unset 移除字段。
本页内容
MongoDB 文档可以包含嵌入式文档,例如用户记录中的 address 对象。投影用于控制查询返回哪些字段。例如,选择 address.city 会返回该嵌套值,同时保留其嵌套结构。对于简单的查询结果,使用 find() 投影;需要在聚合管道中调整文档结构时,使用 $project;需要从管道结果中移除指定字段时,使用 $unset。
理解 MongoDB 中的嵌套字段投影
假设一个文档包含 name 和 address 字段,而 address 又包含 street、city 和 country。嵌套路径使用点表示法,例如 address.city。投影会改变返回的文档,但不会修改存储的源文档。以下示例均使用相同的文档结构。在 find() 投影中,除非明确排除,否则默认会包含 _id。
使用点表示法配合 find() 选择嵌套字段
若只想返回嵌套地址中的城市,请包含对应的点分隔路径。下面的 MongoDB shell 表达式仅用于说明语法,配置的运行环境不会执行它:
db.users.find({}, { "address.city": 1, "_id": 0 })
返回的结构为 { "address": { "city": "New York" } }。如果希望每个结果都保留标识符,请省略 _id: 0。若要排除某个嵌套路径并保留其他字段,可使用 0,例如 { "address.country": 0 }。
包含字段的投影通常不能同时混用包含和排除字段。唯一的特殊情况是 _id:包含其他路径时,可以将它排除。对于其他字段,请选择包含投影或排除投影其中一种。
运行此示例:
本节中的代码以及显示的标签或输出仍为英文。
document = {"name": "Ava", "address": {"city": "New York", "country": "USA"}}
result = {"address": {"city": document["address"]["city"]}}
print(result)
{'address': {'city': 'New York'}}
这个简短的 Python 示例展示了返回结果的嵌套结构;它不会连接到 MongoDB。上面的 MongoDB 查询使用了对应的点分隔路径。示例代码和输出中的文本仍为英文;输出展示了只保留嵌套城市字段后的结构。
使用 $project 聚合阶段调整嵌套字段结构
在聚合管道中,$project 可以包含嵌套路径,也可以将源路径映射到输出字段。例如,{ $project: { _id: 0, city: "$address.city", name: 1 } } 会将 city 放在顶层,并与 name 一同返回。相反,直接包含路径的写法 { $project: { "address.city": 1, _id: 0 } } 会保留 address.city 的嵌套结构。当管道需要特定的输出结构时,$project 会很有用。表达式也可以计算输出值;请确保每个表达式引用的字段都存在于输入文档中。
使用 $unset 聚合阶段排除嵌套字段
在聚合中使用 $unset 阶段,可以移除一个或多个路径,同时保留其他字段:{ $unset: ["address.country"] }。点分隔路径会从管道结果中移除相应的嵌套字段。$unset 会改变继续流经管道的字段,但不会筛除文档。若要筛选文档,请改用查询条件或 $match 阶段。这里介绍的是聚合功能,与使用相同名称的更新运算符不同。
如何选择查询投影或聚合
如果查询只需包含或排除返回文档中的字段,请配合点表示法使用 find()。如果聚合需要重命名路径、计算值或定义特定的输出结构,请选择 $project。如果管道需要保留大多数字段,只移除少数字段,请选择 $unset。$addFields 会添加或替换字段,同时保留文档的其余部分,因此不能替代投影来选择要返回的字段。这三种方式都会影响结果,而不会修改存储的文档。