From 2f101d0b201e215014a034d53cfd61a085c53d10 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 21 Aug 2023 09:58:59 -0400 Subject: [PATCH] fix(query+populate): add `refPath` to projection by default, unless explicitly excluded Fix mongodb-js/mongoose-autopopulate#96 --- lib/helpers/query/selectPopulatedFields.js | 13 +++++++ .../query.selectPopulatedFields.test.js | 36 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 test/helpers/query.selectPopulatedFields.test.js diff --git a/lib/helpers/query/selectPopulatedFields.js b/lib/helpers/query/selectPopulatedFields.js index 92f1d87e04b..dc96caf6fa4 100644 --- a/lib/helpers/query/selectPopulatedFields.js +++ b/lib/helpers/query/selectPopulatedFields.js @@ -21,12 +21,25 @@ module.exports = function selectPopulatedFields(fields, userProvidedFields, popu } else if (userProvidedFields[path] === 0) { delete fields[path]; } + + const refPath = populateOptions[path]?.refPath; + if (typeof refPath === 'string') { + if (!isPathInFields(userProvidedFields, refPath)) { + fields[refPath] = 1; + } else if (userProvidedFields[refPath] === 0) { + delete fields[refPath]; + } + } } } else if (isExclusive(fields)) { for (const path of paths) { if (userProvidedFields[path] == null) { delete fields[path]; } + const refPath = populateOptions[path]?.refPath; + if (typeof refPath === 'string' && userProvidedFields[refPath] == null) { + delete fields[refPath]; + } } } }; diff --git a/test/helpers/query.selectPopulatedFields.test.js b/test/helpers/query.selectPopulatedFields.test.js new file mode 100644 index 00000000000..4a5924b8c64 --- /dev/null +++ b/test/helpers/query.selectPopulatedFields.test.js @@ -0,0 +1,36 @@ +'use strict'; + +const assert = require('assert'); +const selectPopulatedFields = require('../../lib/helpers/query/selectPopulatedFields'); + +describe('selectPopulatedFields', function() { + it('selects refPath', function() { + const fields = { name: 1 }; + const userProvidedFields = { name: 1 }; + const populateOptions = { + parent: { + refPath: 'parentModel' + } + }; + selectPopulatedFields(fields, userProvidedFields, populateOptions); + assert.deepStrictEqual(fields, { + name: 1, + parent: 1, + parentModel: 1 + }); + }); + + it('adds refPath to projection if not deselected by user in exclusive projection', function() { + const fields = { name: 0, parentModel: 0 }; + const userProvidedFields = { name: 0 }; + const populateOptions = { + parent: { + refPath: 'parentModel' + } + }; + selectPopulatedFields(fields, userProvidedFields, populateOptions); + assert.deepStrictEqual(fields, { + name: 0 + }); + }); +});