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

Propagate toObject and toJSON options to implicitly created schemas #13325

Closed
vkarpov15 opened this issue Apr 24, 2023 Discussed in #13303 · 8 comments
Closed

Propagate toObject and toJSON options to implicitly created schemas #13325

vkarpov15 opened this issue Apr 24, 2023 Discussed in #13303 · 8 comments
Labels
enhancement This issue is a user-facing general improvement that doesn't fix a bug or add a new feature
Milestone

Comments

@vkarpov15
Copy link
Collaborator

Discussed in #13303

Originally posted by skrishnan22 April 20, 2023
These are my schemas

user.js

const mongoose = require("mongoose");

const schema = new mongoose.Schema(
  {
    firstName: String,
    companies: {
      type: [
        {
          companyId: {
            type: mongoose.Schema.Types.ObjectId,
          },
          companyName: String,
        },
      ],
      required: true,
    },
  },
  {
    toObject: {
      virtuals: true,
    },
  }
);


schema.virtual("companies.details", {
  ref: "company",
  localField: "companies.companyId",
  foreignField: "_id",
  justOne: true,
});

schema.set("collection", "users");

module.exports = mongoose.model("user", schema);

company.js

const mongoose = require("mongoose");

const schema = new mongoose.Schema({
  name: {
    type: String,
  },
  legalName: {
    type: String,
    required: true,
  },
});

schema.set("collection", "companies");

module.exports = mongoose.model("company", schema);

On running

User.findOne({firstName:'ABC'}).populate('companies.details');

in mongoose 5, companies.details is being populated correctly, but in mongoose 6 the populate is not happening

The populate works in mongoose 6, if I change the User schema as below. Note the change to companies field

const mongoose = require("mongoose");

const schema = new mongoose.Schema(
  {
    firstName: String,
    email: String,
    companies: {
      type: [{}],
      required: true,
    },
  },
  {
    toObject: {
      virtuals: true,
    },
  }
);

schema.virtual("companies.details", {
  ref: "company",
  localField: "companies.companyId",
  foreignField: "_id",
  justOne: true,
});

schema.set("collection", "users");

module.exports = mongoose.model("user", schema);

Is this expected change when migrating from 5 to 6 and if so what is the best way to make it work with versions 6 and above

@vkarpov15 vkarpov15 added the has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue label Apr 24, 2023
@vkarpov15 vkarpov15 added this to the 6.10.6 milestone Apr 24, 2023
@IslandRhythms IslandRhythms added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue and removed has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. labels Apr 26, 2023
@IslandRhythms
Copy link
Collaborator

This bug is also present on mongoose 7. What's interesting is that although it won't print to the console when you view the entire doc, the property is still there when you attempt to access that specific property.

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema(
  {
    firstName: String,
    companies: {
      type: [
        {
          companyId: {
            type: mongoose.Schema.Types.ObjectId,
          },
          companyName: String,
        },
      ],
      required: true,
    },
  },
  {
    toObject: {
      virtuals: true,
    },
    toJSON: { virtuals: true }
  }
);

// const userSchema = new mongoose.Schema(
//   {
//     firstName: String,
//     email: String,
//     companies: {
//       type: [{}],
//       required: true,
//     },
//   },
//   {
//     toObject: {
//       virtuals: true,
//     },
//   }
// );


userSchema.virtual("companies.details", {
  ref: "company",
  localField: "companies.companyId",
  foreignField: "_id",
  justOne: true,
});

userSchema.set("collection", "users");

const User = mongoose.model("user", userSchema);


const companySchema = new mongoose.Schema({
  name: {
    type: String,
  },
  legalName: {
    type: String,
    required: true,
  },
});

companySchema.set("collection", "companies");

const Company = mongoose.model("company", companySchema);

async function run() {
  await mongoose.connect('mongodb://localhost:27017');
  await mongoose.connection.dropDatabase();

  const company = await Company.create({
    name: 'Google',
    legalName: 'Alphabet Inc'
  });
  const user = await User.create({
    firstName: 'Test',
    companies: [{ companyId: company._id, companyName: 'Google' }]
  });

  const test = await User.findOne().populate('companies.details');
  console.log('what is test', test, test.companies[0].details);
}

run();

@vkarpov15
Copy link
Collaborator Author

@IslandRhythms that's because you're missing a toObject({ virtuals: true }). console.log('what is test', test.toObject({ virtuals: true }), test.companies[0].details);

@vkarpov15 vkarpov15 removed this from the 6.11.0 milestone Apr 27, 2023
@vkarpov15 vkarpov15 added can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. and removed confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. labels Apr 27, 2023
@IslandRhythms
Copy link
Collaborator

But its set in the schema? Doesn't that remove the need to include that in the consolel log?

@vkarpov15
Copy link
Collaborator Author

Good point. companies is an array of subdocuments, and subdocuments have their own schema. But we should consider propagating toObject and toJSON to implicitly created schemas, like we do with strict, etc.

@vkarpov15 vkarpov15 removed the can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. label May 1, 2023
@vkarpov15 vkarpov15 added this to the 7.2.0 milestone May 1, 2023
@vkarpov15 vkarpov15 changed the title Mongoose 6: Populate not working on array field with defined subdocument schema Propagate toObject and toJSON options to implicitly created schemas May 1, 2023
@vkarpov15 vkarpov15 added the enhancement This issue is a user-facing general improvement that doesn't fix a bug or add a new feature label May 1, 2023
vkarpov15 added a commit that referenced this issue May 13, 2023
vkarpov15 added a commit that referenced this issue May 14, 2023
enhancement: propagate `toObject` and `toJSON`
@hasezoey
Copy link
Collaborator

should there also be a way to pass down options for toObject / toJSON to explicit schemas and not just via the explicit schemas schema-options? (to not require a workaround like for typegoose/typegoose#835)

@vkarpov15
Copy link
Collaborator Author

@hasezoey 2 ideas come to mind:

  1. An inheritParentSchemaOptions option for nested schemas
  2. A global option to make child schemas inherit the same set of schema options that we pass to implicitly created schemas. This could also be achieved with a plugin.
  3. Just a thought: would it be possible for Typegoose to use implicitly created schemas, or is that not easy?

@hasezoey
Copy link
Collaborator

Just a thought: would it be possible for Typegoose to use implicitly created schemas, or is that not easy?

i think it would be possible, but was asking about a general option so that when calling doc.toObject({ virtual: true }) all subdocuments would also have virtuals shown, even if they dont have explicit schema-options set

@vkarpov15
Copy link
Collaborator Author

AFAIK that's not a problem, doc.toObject({ virtuals: true }) would apply virtuals on all subdocuments, because the toObject() function's options always overwrite the schema-level toObject options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement This issue is a user-facing general improvement that doesn't fix a bug or add a new feature
Projects
None yet
Development

No branches or pull requests

3 participants