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

Allow specifying default projection for populated fields #6029

Closed
kherock opened this issue Jan 23, 2018 · 6 comments
Closed

Allow specifying default projection for populated fields #6029

kherock opened this issue Jan 23, 2018 · 6 comments
Labels
new feature This change adds new functionality, like a new method or class
Milestone

Comments

@kherock
Copy link
Contributor

kherock commented Jan 23, 2018

Do you want to request a feature or report a bug?
Feature

What is the current behavior?
Currently, if you populate on a field with no projection specified, it puts the entire document in by default.

I've realized that most of the time I really only want a pretty limited subset of those fields when I'm populating a field for a document (for example, the first and last names of a user vs. all of their related profile data). It also tends to get messy when there are multiple fields to populate. I think a simple way to introduce this would be another property in schema definitions that can be used when using ref. For example, something like this would work:

const messageSchema = new Schema({
  text: String,
  date: Date,
  user: { ref: 'User', populate: 'firstName lastName' }
})

// ...

const message = await Message.findById(id).populate('user')
console.log(message.user) // { firstName: 'Kyle', lastName: 'Herock' }

Please mention your node.js, mongoose and MongoDB version.
Node 8, Mongoose 5.0, MongoDB 3.6

@sobafuchs
Copy link
Contributor

sure, i can label this a feature request, but how would you recommend overriding the defaults in the case where you do want the entire object? Would the user need to specify each and every field in the schema then?

@sobafuchs sobafuchs added the new feature This change adds new functionality, like a new method or class label Jan 27, 2018
@AbdullahAli
Copy link

Any update on this please? This would be very useful!

@vkarpov15 vkarpov15 added this to the 5.x Unprioritized milestone May 3, 2020
@vkarpov15
Copy link
Collaborator

@AbdullahAli no updates yet, please follow this issue for updates.

@daveteu
Copy link

daveteu commented Aug 29, 2020

Populate is a 2 edge sword. It provides convenience, yet at the expense of convenience, you may accidentally leak passwords and other sensitive information when you populate a user field without specifying the fields.

IMO, by default, populate should require developers to choose the fields to populate, or { path: 'user', select : 1 } to populate everything.

I wonder how many passwords are being leaked unnecessarily because developers don't check the returned objects.

Possible workarounds
.populate('field', 1) //1 to indicate all
or
.populate( path: 'field', select: 1) to indicate all

Thanks for the hardwork.

@vkarpov15
Copy link
Collaborator

@daveteu thanks for your feedback. However, that sounds like a symptom of bad schema design, like the anti-pattern of storing password hashes on user documents. If you find yourself wanting to exclude a field all the time, then you should consider storing it in a separate model. Store what you query for.

We'll bump this issue up for v5.11 👍

@vkarpov15 vkarpov15 modified the milestones: 5.x Unprioritized, 5.11 Aug 31, 2020
@vkarpov15
Copy link
Collaborator

In v5.11 you'll be able to do this:

    const parentSchema = Schema({
      child: {
        type: 'ObjectId',
        ref: 'Child',
        populate: { select: 'name' }
      }
    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature This change adds new functionality, like a new method or class
Projects
None yet
Development

No branches or pull requests

6 participants