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

How to programmatically create a new subdocument from outside document? #9076

Closed
niftylettuce opened this issue May 30, 2020 · 3 comments
Closed

Comments

@niftylettuce
Copy link
Contributor

For example, the only way right now that is documented to create a subdocument is:

const Model = mongoose.model('MyModel', schema);
const obj = new Model();
const subDocument = obj.someSubSchema.create(); // <--

I think it might be nice to document, if possible, a way to create the subDocument without having to create an instance of the model?

@vkarpov15
Copy link
Collaborator

Document arrays have a create() method:

'use strict';
  
const mongoose = require('mongoose');

mongoose.set('useFindAndModify', false);

const { Schema } = mongoose;

run().catch(err => console.log(err));

async function run() {
  await mongoose.connect('mongodb://localhost:27017/test', {
    useNewUrlParser: true,
    useUnifiedTopology: true
  });

  await mongoose.connection.dropDatabase();

  const nestedSchema = new Schema({ name: String });
  nestedSchema.methods.getAnswer = () => 42;

  const schema = new Schema({
    arr: [nestedSchema]
  });
  const Model = mongoose.model('Test', schema);

  const doc = new Model({ arr: [] });
  const subdoc = doc.arr.create({ name: 'foo' });

  console.log(subdoc instanceof mongoose.Document); // true
  console.log(subdoc.getAnswer()); // 42
}

But I've struggled to find a case where this is useful. Can you elaborate on your use case for this?

@vkarpov15 vkarpov15 added the discussion If you have any thoughts or comments on this issue, please share them! label Jun 4, 2020
@niftylettuce
Copy link
Contributor Author

Yes, see my comment/solution here: mblarsen/mongoose-hidden#58 (comment)

@vkarpov15 vkarpov15 added this to the 5.9.19 milestone Jun 11, 2020
@vkarpov15 vkarpov15 removed the discussion If you have any thoughts or comments on this issue, please share them! label Jun 11, 2020
@vkarpov15 vkarpov15 modified the milestones: 5.9.19, 5.9.20 Jun 15, 2020
@vkarpov15
Copy link
Collaborator

@niftylettuce I took a closer look at this, it looks like your issue won't be solved by .create() since you want to convert a POJO to a subdoc without creating a top-level document. In that case, you can use SchemaType#cast() to make Mongoose cast the POJO as shown below:

'use strict';
  
const mongoose = require('mongoose');

mongoose.set('useFindAndModify', false);

const { Schema } = mongoose;

run().catch(err => console.log(err));

async function run() {
  await mongoose.connect('mongodb://localhost:27017/test', {
    useNewUrlParser: true,
    useUnifiedTopology: true
  });

  await mongoose.connection.dropDatabase();

  const nestedSchema = new Schema({ name: String });
  nestedSchema.methods.getAnswer = () => 42;

  const schema = new Schema({
    arr: [nestedSchema],
    singleNested: nestedSchema
  });
  const Model = mongoose.model('Test', schema);

  // Cast to doc array
  let subdoc = Model.schema.path('arr').cast([{ name: 'foo' }])[0];
  console.log(subdoc instanceof mongoose.Document); // true
  console.log(subdoc.getAnswer()); // 42

  // Cast to single nested subdoc
  subdoc = Model.schema.path('singleNested').cast({ name: 'bar' });
  console.log(subdoc instanceof mongoose.Document); // true
  console.log(subdoc.getAnswer()); // 42
}

More on schematypes: https://mongoosejs.com/docs/schematypes.html

@vkarpov15 vkarpov15 removed this from the 5.9.20 milestone Jun 18, 2020
vkarpov15 added a commit that referenced this issue Jul 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants