mongodb-js / mongoose-autopopulate

Always populate() certain fields in your mongoose schemas
Apache License 2.0
222 stars 36 forks source link

Projection issues with autopopulated fields #50

Closed eyal88 closed 5 years ago

eyal88 commented 5 years ago

Setting autopopulate: true to a field in a schema makes it being projected automatically. Trying to explicitly omit it with: { "field": 0 } in the query results in an error:

"Projection cannot have a mix of inclusion and exclusion."

Demo

Schema A

let SchemaA = new Schema({
  name: {
    type: String,
    default: ''
  },
  type: {
    type: String,
    ref: 'SchemaB',
    default: null,
    autopopulate: true
  }
});

Schema B

let SchemaB = new Schema({
  name: {
    type: String,
    default: ''
  }
});

Init

let b = new B({ "name": "b" });
let a = new A({ "name": "a", "type": b });

Queries

Query 1

A.findOne({ "name": "a" }, ['name'])
  .then(doc => { console.log(doc) })

Query 2

A.findOne({ "name": "a" }, { "name": 1, "type": 0 })
  .then(doc => { console.log(doc) })

Actual result

Query 1

{
  "name": "a" , 
  "type": {
    "name": "b"
  }
}

Query 2 Projection cannot have a mix of inclusion and exclusion.

Expected result

{
  "name": "a" 
}
vkarpov15 commented 5 years ago

Mongoose automatically projects in populated fields, including ones this plugin populates. Try this: A.findOne().select('name -type')

eyal88 commented 5 years ago

Thanks @vkarpov15. You'r right about the automatic inclusion of populated fields. Omitting a field like '-type' does work, however it can't be done with an explicit inclusion of the 'name' field. That's where the error came from.

From mongoose docs:

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://mongoosejs.com/docs/api.html#query_Query-select

Thanks again!