Skip to content

Cannot update array of arrays using Document.set #8689

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

Closed
BrunoGodefroy opened this issue Mar 19, 2020 · 1 comment
Closed

Cannot update array of arrays using Document.set #8689

BrunoGodefroy opened this issue Mar 19, 2020 · 1 comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@BrunoGodefroy
Copy link

BrunoGodefroy commented Mar 19, 2020

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

What is the current behavior?
Setting the content of an array of arrays throws a MongoError: The positional operator did not find the match needed from the query.

Doing exactly the same update with updateOne works fine.

If the current behavior is a bug, please provide the steps to reproduce.

Assuming a connection to a mongo server has been established, the following jest test should demonstrate the issue (I have the same bug outside of the jest environment I just used it for convenience):

describe('Test mongoose', () => {
  const schema = new mongoose.Schema({
    name: String,
    array: [[{
      label: String,
      value: String,
    }]],
  });
  const MyModel = mongoose.model('MyModel', schema);
  const updateQuery = {
    'array.0': [{
      label: 'hello',
      value: 'world',
    }],
  };

  test('It works to update nested array using updateOne', async () => {
    const doc = await new MyModel({ name: 'foo' }).save();
    await MyModel.updateOne({ _id: doc._id }, { $set: updateQuery });

    const updatedDoc = await MyModel.findOne({ _id: doc._id });
    expect(updatedDoc.array[0][0].label).toBe('hello');
    expect(updatedDoc.array[0][0].value).toBe('world');
    // Success!
  });

  test('It works to update nested array using set', async () => {
    const doc = await new MyModel({ name: 'foo' }).save();
    await doc.set(updateQuery).save();  // Fails MongoError: The positional operator did not find the match needed from the query.

    const updatedDoc = await MyModel.findOne({ _id: doc._id });
    expect(updatedDoc.array[0][0].label).toBe('hello');
    expect(updatedDoc.array[0][0].value).toBe('world');
  });
});

After a git bisect I have found the commit that caused the issue: 51c6776

Downgrading to 5.7.12 fixes the issue.

What is the expected behavior?
Should update the nested array using doc.set

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
mongoose: 5.7.13
mongoDB: 4.2.0
Node: 10.16.0

@AbdelrahmanHafez
Copy link
Collaborator

I can confirm that this is an issue: the following gets sent in the case of MyModel.updateOne(...):

{
  '$set': {
    'array.0': [{
      label: 'hello',
      value: 'world'
    }]
  }
}

using doc.set(updateQuery).save() adds an'array.$': [[undefined]] to the update sent to Mongo:

{
  '$set': {
    'array.$': [
      [undefined]
    ],
    'array.0': [{
      label: 'hello',
      value: 'world'
    }]
  }
}

@vkarpov15 vkarpov15 added this to the 5.9.6 milestone Mar 23, 2020
@vkarpov15 vkarpov15 added the has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue label Mar 23, 2020
vkarpov15 added a commit that referenced this issue Mar 23, 2020
@vkarpov15 vkarpov15 added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. and removed has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue labels Mar 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
Development

No branches or pull requests

3 participants