Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MongoDB

MongoDB 查询返回特定字段:使用 findOne() Projection

本文演示如何使用 findOne() 配合 Projection (投影) 参数,仅返回文档中指定的特定字段,而非完整文档。

语法

db.yourCollectionName.findOne(
  { "yourFieldName1": yourValue },  // Query Filter
  { yourFieldName2: 1 }             // Projection: 1=包含, 0=排除
);

创建示例数据

> db.particularFieldDemo.insertOne({"EmployeeName":"John Smith","EmployeeAge":26,"EmployeeTechnology":"MongoDB"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9b4abb50a6c6dd317ada2") }
> db.particularFieldDemo.insertOne({"EmployeeName":"Chris Brown","EmployeeAge":28,"EmployeeTechnology":"Java"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9b4d2b50a6c6dd317ada3") }
> db.particularFieldDemo.insertOne({"EmployeeName":"David Miller","EmployeeAge":30,"EmployeeTechnology":"MySQL"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9b4e8b50a6c6dd317ada4") }
> db.particularFieldDemo.insertOne({"EmployeeName":"John Doe","EmployeeAge":31,"EmployeeTechnology":"C++"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9b527b50a6c6dd317ada5") }

显示所有数据

> db.particularFieldDemo.find().pretty();
{ "_id" : ObjectId("5cd9b4abb50a6c6dd317ada2"), "EmployeeName" : "John Smith", "EmployeeAge" : 26, "EmployeeTechnology" : "MongoDB" }
{ "_id" : ObjectId("5cd9b4d2b50a6c6dd317ada3"), "EmployeeName" : "Chris Brown", "EmployeeAge" : 28, "EmployeeTechnology" : "Java" }
{ "_id" : ObjectId("5cd9b4e8b50a6c6dd317ada4"), "EmployeeName" : "David Miller", "EmployeeAge" : 30, "EmployeeTechnology" : "MySQL" }
{ "_id" : ObjectId("5cd9b527b50a6c6dd317ada5"), "EmployeeName" : "John Doe", "EmployeeAge" : 31, "EmployeeTechnology" : "C++" }

查询:EmployeeTechnology = "Java",仅返回 EmployeeName

> db.particularFieldDemo.findOne({"EmployeeTechnology":"Java"}, {EmployeeName:1});

结果

{ "_id" : ObjectId("5cd9b4d2b50a6c6dd317ada3"), "EmployeeName" : "Chris Brown" }

Projection 详解

  • { EmployeeName: 1 } - 包含 EmployeeName 字段
  • _id 默认包含,如需排除:{ EmployeeName: 1, _id: 0 }
  • 不能混合 0 和 1 (除 _id 外):{ name: 1, age: 0 } ❌
  • 嵌套字段:{ "address.city": 1 }
  • Array 切片:{ tags: { $slice: 5 } } (仅前 5 个)

find() 也支持相同 Projection

// 返回所有匹配文档的指定字段
db.particularFieldDemo.find(
  {"EmployeeTechnology": "Java"},
  {EmployeeName: 1, _id: 0}
);

Aggregation $project 对比

// 更强大:可计算新字段、重命名、数组展开等
db.particularFieldDemo.aggregate([
  { $match: { EmployeeTechnology: "Java" } },
  { $project: { 
    _id: 0, 
    name: "$EmployeeName", 
    tech: "$EmployeeTechnology",
    ageInMonths: { $multiply: ["$EmployeeAge", 12] }
  }}
]);

性能优势

  • 减少网络传输数据量
  • 减少内存占用 (客户端/驱动层)
  • 配合覆盖索引可实现 Covered Query (纯索引扫描,不访问文档)

覆盖索引示例

// 创建索引包含查询字段和投影字段
db.particularFieldDemo.createIndex({ EmployeeTechnology: 1, EmployeeName: 1 });

// 此查询可完全由索引满足 (covered query)
db.particularFieldDemo.find(
  { EmployeeTechnology: "Java" },
  { EmployeeName: 1, _id: 0 }
).explain("executionStats"); // 查看 executionStats: totalKeysExamined > 0, totalDocsExamined: 0