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

Add lodash docs explaining that you shouldn't deepClone() documents #12559

Closed
2 tasks done
piyushk96 opened this issue Oct 17, 2022 · 2 comments · Fixed by #12609
Closed
2 tasks done

Add lodash docs explaining that you shouldn't deepClone() documents #12559

piyushk96 opened this issue Oct 17, 2022 · 2 comments · Fixed by #12609
Labels
docs This issue is due to a mistake or omission in the mongoosejs.com documentation
Milestone

Comments

@piyushk96
Copy link

piyushk96 commented Oct 17, 2022

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Mongoose version

6.6.5

Node.js version

16.15.1

MongoDB server version

4.4.13

Typescript version (if applicable)

No response

Description

In continuation to #6507. Lodash cloneDeep is now working perfectly when there is single level array subdocuments as mentioned in this comment but mongoose is still throwing following error when there is array of array subdocuments

myProject/node_modules/mongoose/lib/types/ArraySubdocument.js:149
  return this.__parentArray.$path() + '.' + this.__index + '.' + path;
                            ^
TypeError: this.__parentArray.$path is not a function
    at EmbeddedDocument.ArraySubdocument.$__pathRelativeToParent (/Users/myuser/myProject/node_modules/mongoose/lib/types/ArraySubdocument.js:149:29)
    at EmbeddedDocument.Subdocument.$isValid (/Users/myuser/myProject/node_modules/mongoose/lib/types/subdocument.js:150:25)
    at /Users/piyushkakkar/office/preppapi/node_modules/mongoose/lib/document.js:2802:18
    at processTicksAndRejections (node:internal/process/task_queues:78:11)

Steps to Reproduce

Demo Code:

const cloneDeep = require('lodash.cloneDeep');
const mongoose = require('mongoose');

async function run() {
  await mongoose.connect('mongodb://localhost:27017/test5');
  const arr2Schema = new mongoose.Schema({ _id: false, prop1: String });
  const arr1Schema = new mongoose.Schema({ _id: false, arr2: [arr2Schema] });
  const Test = mongoose.model(
    'Test',
    new mongoose.Schema({
      arr1: [arr1Schema],
      field: String,
    }),
  );

  let doc = new Test({ arr1: [{ arr2: [{ prop1: 'test' }] }] });
  await doc.save();

  const doc2 = await Test.findById(doc._id);
  const newDoc = cloneDeep(doc2).set({ field: 'test' });

  await newDoc.save(); // throws error
  console.log(newDoc);
}

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

run this js script

Expected Behavior

Document should be updated without any error

@IslandRhythms
Copy link
Collaborator

const cloneDeep = require('lodash/cloneDeep'); // fixed import
const mongoose = require('mongoose');

async function run() {
  await mongoose.connect('mongodb://localhost:27017/test5');
  const arr2Schema = new mongoose.Schema({ _id: false, prop1: String });
  const arr1Schema = new mongoose.Schema({ _id: false, arr2: [arr2Schema] });
  const Test = mongoose.model(
    'Test',
    new mongoose.Schema({
      arr1: [arr1Schema],
      field: String,
    }),
  );

  let doc = new Test({ arr1: [{ arr2: [{ prop1: 'test' }] }] });
  await doc.save();

  const doc2 = await Test.findById(doc._id);
  const newDoc = cloneDeep(doc2).set({ field: 'test' });

  await newDoc.save(); // throws error
  console.log(newDoc);
}

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

@IslandRhythms IslandRhythms added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Oct 17, 2022
@vkarpov15 vkarpov15 added this to the 6.6.8 milestone Oct 24, 2022
@vkarpov15
Copy link
Collaborator

I took a look and unfortunately we can't support cloneDeep() on documents with arrays in Mongoose 6. cloneDeep() has no way of knowing whether an object is a proxy, and we switched to using proxies for arrays in Mongoose 6.

We're planning on shipping a $clone() function in v6.8 that will allow you to do the following. See #11849 and #12549 for more info.

  const doc2 = await Test.findById(doc._id);
  const newDoc = doc2.$clone().set({ field: 'test' });

  await newDoc.save(); // works
  console.log(newDoc);

In the meantime, since $clone() isn't shipped yet, you should do the following:

  const doc2 = await Test.findById(doc._id);
  const newDoc = new Test().init(doc2.toObject()).set({ field: 'test' });

  await newDoc.save(); // works
  console.log(newDoc);

@vkarpov15 vkarpov15 removed this from the 6.7.1 milestone Oct 28, 2022
@vkarpov15 vkarpov15 added docs This issue is due to a mistake or omission in the mongoosejs.com documentation and removed confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. labels Oct 28, 2022
@vkarpov15 vkarpov15 added this to the 6.7.1 milestone Oct 28, 2022
@vkarpov15 vkarpov15 reopened this Oct 28, 2022
@vkarpov15 vkarpov15 changed the title Deep cloning a mongoose model with arrays of arrays doesn't work Add lodash docs explaining that you shouldn't deepClone() documents Oct 28, 2022
vkarpov15 added a commit that referenced this issue Nov 1, 2022
docs: add Lodash guide highlighting issues with cloneDeep()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs This issue is due to a mistake or omission in the mongoosejs.com documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants