find()的projection参数需统一用1或0指定字段,_id是唯一可混用的例外;嵌套字段用点号语法如values.cou_value;Spring Data中推荐用Query.fields().include()安全操作。

用 find() 的 projection 参数指定多个字段
直接在 find() 第二个参数里列明要返回的字段,值设为 1;不需要的字段(包括 _id)设为 0。MongoDB 不允许在同一 projection 中混用 1 和 0(_id 是唯一例外)。
-
_id默认返回,如不需,必须显式写_id: 0 - 只写
{ name: 1, age: 1 }等价于{ name: 1, age: 1, _id: 1 } - 如果想排除
_id同时保留其他字段,必须写成{ name: 1, age: 1, _id: 0 } - 不能写
{ name: 1, age: 0 }—— 这会报错Projection cannot have a mix of inclusion and exclusion
嵌套字段(子文档/数组内字段)怎么取?
用点号语法(.)直接访问嵌套路径,比如 values.cou_value 或 address.city。这种写法只在 projection 中生效,且仅返回该字段值,不会带出整个父对象。
- 写
{"values.cou_value": 1, "values.flag": 1}→ 返回的是扁平结构:{"values.cou_value": "12", "values.flag": "N"} - 不写
values字段本身 →values数组整体不会出现在结果里,只保留你点名的子字段 - 如果数组里有多个元素,所有匹配路径的值都会被提取(即每个文档中所有
values元素里的cou_value都会拉出来) - 若只想过滤数组内容(比如只取
values中pollutant_code === "B02"的那条),得用$filter配合聚合管道,find()的 projection 做不到
Spring Data MongoDB 里用 MongoTemplate 怎么写?
别拼 raw JSON,用 Query.fields().include(...) 更安全、类型友好。字段名支持点号,和 shell 一致。
-
query.fields().include("name", "age", "profile.email", "tags.0")是合法的 -
tags.0表示只取数组第一个元素的整个对象(不是某个子字段),但要注意:它仍会返回完整tags[0]对象,不是投影其内部字段 - 如果字段名含特殊字符(如
.、$),要用双反斜杠转义,例如"data\.v1" - 调用
fields().exclude("_id")和include(...)混用会覆盖行为,建议统一用include显式声明
为什么有时字段没返回,或返回了空数组?
常见原因不是语法错,而是数据结构不匹配。projection 只负责“摘字段”,不负责“保存在”。
- 字段路径不存在(如文档里根本没有
values字段)→ 对应 key 在结果里直接消失,不会留null或空对象 - 点号路径指向一个数组,但你想取的子字段只在部分元素里存在 → 缺失位置返回
null(Java 驱动可能映射为null,而 shell 显示为缺失) - 用
include列了values.pollutant_code,但实际数据是values为空数组 → 结果里不会有values.pollutant_code这个 key - 字段名大小写敏感,
"Values"和"values"是两个东西


















