diff --git a/lib/query.js b/lib/query.js index 4dfd065f639..cc919b35ade 100644 --- a/lib/query.js +++ b/lib/query.js @@ -902,7 +902,6 @@ Query.prototype.select = function select() { fields[field] = include; userProvidedFields[field] = include; } - return this; } diff --git a/lib/queryhelpers.js b/lib/queryhelpers.js index baa548df0e4..f48790615e0 100644 --- a/lib/queryhelpers.js +++ b/lib/queryhelpers.js @@ -241,10 +241,9 @@ exports.applyPaths = function applyPaths(fields, schema) { analyzeSchema(schema); - let i; switch (exclude) { case true: - for (i = 0; i < excluded.length; ++i) { + for (let i = 0; i < excluded.length; ++i) { fields[excluded[i]] = 0; } break; @@ -255,14 +254,24 @@ exports.applyPaths = function applyPaths(fields, schema) { schema.paths['_id'].options.select === false) { fields._id = 0; } - for (i = 0; i < selected.length; ++i) { + for (let i = 0; i < selected.length; ++i) { fields[selected[i]] = 1; } break; case undefined: + if (fields == null) { + break; + } + // Any leftover plus paths must in the schema, so delete them (gh-7017) + for (const key of Object.keys(fields || {})) { + if (key.charAt(0) === '+') { + delete fields[key]; + } + } + // user didn't specify fields, implies returning all fields. - // only need to apply excluded fields - for (i = 0; i < excluded.length; ++i) { + // only need to apply excluded fields and delete any plus paths + for (let i = 0; i < excluded.length; ++i) { fields[excluded[i]] = 0; } break; diff --git a/test/schema.select.test.js b/test/schema.select.test.js index 12af15fdc73..ca06a4fd077 100644 --- a/test/schema.select.test.js +++ b/test/schema.select.test.js @@ -397,16 +397,19 @@ describe('schema select option', function() { return co(function*() { yield db; - yield db.db.collection('gh7017').insertOne({ + yield db.collection('gh7017').insertOne({ a: 'foo', b: 'bar', c: 'baz' }); - const doc = yield M.find({}, '+c').then(res => res[0]); + const q = M.find({}).select('+c'); + const doc = yield q.then(res => res[0]); + assert.deepEqual(q._fields, { a: 0, b: 0 }); + assert.strictEqual(doc.a, void 0); assert.strictEqual(doc.b, void 0); - assert.equal(doc.c, 'baz'); + assert.equal(doc.toObject().c, 'baz'); }); }); });