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

Document.set doesn't work on nested Maps or plain non-strict objects. #13327

Closed
2 tasks done
sgpinkus opened this issue Apr 25, 2023 · 2 comments
Closed
2 tasks done

Document.set doesn't work on nested Maps or plain non-strict objects. #13327

sgpinkus opened this issue Apr 25, 2023 · 2 comments
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@sgpinkus
Copy link
Contributor

sgpinkus commented Apr 25, 2023

Prerequisites

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

Mongoose version

7.0.5

Node.js version

v16.18.1

MongoDB server version

mongo:5.0.9

Typescript version (if applicable)

No response

Description

Deep Document.set using a key with 2 more dots in it like x.set('a.b.c', 1) doesn't seem to work for:

  • Map of Maps
  • Map of Mixed
  • Plain schema object with strict: false.

It should. It does work for just a top level Mixed type.

Steps to Reproduce

const mongoose = require('mongoose');
const { model, Schema } = mongoose;

var TestSchema =  new Schema({
  a: Schema.Types.Mixed,
  b: {
    type: Map,
    of: Schema.Types.Mixed,
    default: {},
  },
  c: {
    type: Map,
    of: {
      type: Map,
      of: Schema.Types.Mixed,
      default: {},
    },
    default: {},
  },
  d: new Schema({
    }, {
      strict: false,
      _id: false,
    },
  )
});

var Test = model('Test', TestSchema);

async function main() {
  await mongoose.connect('mongodb://localhost:27017/test');
  await mongoose.connection.dropDatabase();
  await setThings(); // Only sets a.x.y
}

async function setThings() {
  var x = new Test({});
  x.set('a.x.y', 1);
  x.set('b.x.y', 1);
  x.set('c.x.y', 1);
  x.set('d.x.y', 1);
  await x.save();
  console.log(x.toObject());
}

main()
  .then(() => process.exit())
  .catch((e) => { console.error(e); process.exit(); })

Gives:

{
  b: Map(1) { 'x' => {} },
  c: Map(0) {},
  _id: new ObjectId("644799e0f03d7fd6496855fb"),
  a: { x: { y: 1 } },
  __v: 0
}

Expected Behavior

All the Document.set calls should work.

@IslandRhythms IslandRhythms added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Apr 26, 2023
@vkarpov15 vkarpov15 added this to the 7.1.1 milestone Apr 26, 2023
vkarpov15 added a commit that referenced this issue Apr 28, 2023
vkarpov15 added a commit that referenced this issue May 4, 2023
fix(document): handle calling `set()` underneath a strict: false subdocument path from the top-level document
@vkarpov15 vkarpov15 modified the milestones: 7.1.1, 7.1.2 May 4, 2023
@vkarpov15
Copy link
Collaborator

We fixed one case with #13339, we'll work on the others next week.

vkarpov15 added a commit that referenced this issue May 8, 2023
fix(document): handle set() from top-level underneath a map of mixed
@vkarpov15 vkarpov15 modified the milestones: 7.1.2, 7.2.1 May 19, 2023
@vkarpov15
Copy link
Collaborator

Confirmed that #13386 and #13339 are sufficient to make this work, output from OP's script is now:

{
  b: Map(1) { 'x' => { y: 1 } },
  c: Map(1) { 'x' => Map(1) { 'y' => 1 } },
  _id: new ObjectId("646d2c7ba45fbc3e4fe5af82"),
  a: { x: { y: 1 } },
  d: { x: { y: 1 } },
  __v: 0
}

@vkarpov15 vkarpov15 modified the milestones: 7.2.1, 7.1.1 May 23, 2023
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