MongoDB投影title字段异常:需重复指定title:1才能生效?
Hey there, let's break down why you're seeing this odd behavior with your aggregation query and how to fix it cleanly.
Why does repeating title:1 work?
MongoDB's $project stage uses a whitelist approach by default. That means:
- Only the fields you explicitly mark with
1(or define new computed fields for) are carried over to the next pipeline stage. - The
_idfield is kept automatically unless you explicitly exclude it with_id:0.
In your query, the first $project includes title:1, so title makes it to the second stage. But your second $project only defines the normalized_rating computed field—you don't explicitly include title here. So MongoDB drops the title field (and any other unmentioned fields) before moving to the next stage. When you add title:1 again in the second $project, you're telling MongoDB to keep that field alongside the new computed one, which is why it shows up in your results.
Fixes to avoid repeating fields
You have two solid options to clean up this query:
1. Explicitly include needed fields in the second $project
If you want to keep the two separate $project stages, just add the fields you want to retain to the second stage:
db.movies.aggregate([ {$match: { languages: {$elemMatch : {$eq: "English"}}, "imdb.rating":{$gte: 1}, "imdb.votes":{$gte: 1}, year: {$gte: 1990} }}, {$project: { scaled_votes: {$add: [ 1, {$multiply: [ 9, {$divide: [ {$subtract: ["$imdb.votes",5]}, {$subtract: [1521105,5]} ]} ]} ]}, "imdb.rating": 1, title: 1 }}, {$project: { normalized_rating: {$avg: ["$scaled_votes", "$imdb.rating"]}, title: 1, // Keep title "imdb.rating": 1 // Keep rating if needed }} ])
2. Merge both $project stages into one (more efficient)
There's no need to split the projection and computed fields into two separate stages. Combining them reduces pipeline overhead and eliminates the need to repeat field definitions:
db.movies.aggregate([ {$match: { languages: {$elemMatch : {$eq: "English"}}, "imdb.rating":{$gte: 1}, "imdb.votes":{$gte: 1}, year: {$gte: 1990} }}, {$project: { title: 1, "imdb.rating": 1, scaled_votes: {$add: [ 1, {$multiply: [ 9, {$divide: [ {$subtract: ["$imdb.votes",5]}, {$subtract: [1521105,5]} ]} ]} ]}, normalized_rating: {$avg: ["$scaled_votes", "$imdb.rating"]} }} ])
This single $project stage computes both scaled_votes and normalized_rating while retaining the title and imdb.rating fields you need, all in one step.
内容的提问来源于stack exchange,提问作者Rahul Raj

