Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'Cannot do exclusion on field in inclusion projection' error when field1 excluded in schema & query.select('field2 -_id') #12670

Closed
2 tasks done
lorand-horvath opened this issue Nov 9, 2022 · 3 comments · Fixed by #12736
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@lorand-horvath
Copy link
Contributor

lorand-horvath commented Nov 9, 2022

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

6.7.2

Node.js version

18.x

MongoDB server version

5.x

Typescript version (if applicable)

No response

Description

I would like to report a long standing bug regarding simultaneous field exclusion in schema and select() query, with -_id not specified as first field.

Steps to Reproduce

Suppose we have field1 excluded from selection/projection in schema:

const schema = new mongoose.Schema({
    field1: {
        type: String,
        select: false
    },
    field2: String
});
const User = mongoose.model('User', schema);

User.find().select('field2 -_id')
    .then(console.log)
    .catch(err => console.log(err.message));

The error returned is Cannot do exclusion on field field1 in inclusion projection.
However, if I first exclude the _id in the select() then the query executes just fine, no error in that case:

User.find().select('-_id field2')

Not sure when this regression was introduced or whether it has ever worked in the first place. @vkarpov15 could you please double check? Thanks for looking into this!

Expected Behavior

Excluding -_id from select() should work irrespective of its position in the list of fields. At the moment it only works when -_id is the first field, then the rest of the included fields.
This issue only occurs when there's another field excluded from select in the schema.

@lorand-horvath
Copy link
Contributor Author

lorand-horvath commented Nov 9, 2022

@vkarpov15 I've just verified and confirm to have the same problem when selecting via the find method's second argument (projection):
User.find({}, {field2: 1, _id: 0}) - throws the error Cannot do exclusion on field field1 in inclusion projection

If I specify _id: 0 as the first, it works fine:
User.find({}, {_id: 0, field2: 1})

@IslandRhythms
Copy link
Collaborator

I'll mark this as a bug because I'm not entirely sure, but this could be expected behavior.

A projection must be either inclusive or exclusive. In other words, you must either list the fields to include (which excludes all others), or list the fields to exclude (which implies all other fields are included). The [_id field is the only exception because MongoDB includes it by default](https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/#suppress-id-field).

Its possible that the way it works it that it sees field2 and thinks "Ok this is an inclusive projection" and then it sees the -_id and goes "wait, can't do that."
Then when you run it the other way: it sees -_id and goes "ok exclusive, but this is _id so I can ignore this" and then sees field2 and goes "ok, inclusive it is".

@IslandRhythms IslandRhythms added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Nov 16, 2022
@lorand-horvath
Copy link
Contributor Author

@IslandRhythms It's obviously a bug and I think it's caused when merging the schema selection/projection (fields marked with select: false) with the query projection (fields passed to .select() or as second argument to .find() ).

The merging should be done by making sure the position of -_id in either projection doesn't influence the decision whether it will finally be an exclusion or inclusion selection (-_id should be allowed in either, irrespective of its position).

@vkarpov15 vkarpov15 modified the milestones: 6.7.4, 6.7.5 Nov 25, 2022
vkarpov15 added a commit that referenced this issue Nov 29, 2022
vkarpov15 added a commit that referenced this issue Nov 30, 2022
fix(query): handle deselecting _id when another field has schema-level `select: false`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
3 participants