Closed
Description
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the bug has not already been reported
Mongoose version
8.15.1
Node.js version
v22.15.0
MongoDB server version
8.0.9
Typescript version (if applicable)
No response
Description
If you have model with Map
field (see repro script, MetaSchema.items
), you can use model.set(path, value)
only if path
does not refer inside the Schema
nested in the Map
, i.e.:
item.set("items.m3", { field: "field3", arr: [4] }); // OK
item.set("items.m2.field", "replaced"); // does not work
item.set("items.m2.arr", [1]); // does not work
Also, if you have nested Map
inside Map
field (see repro script, MetaSchema.nested
), an error is thrown when trying to call set()
with a nested Schema
with a nested Map
, i.e.:
item.set("nested.inserted", { map: new Map([["a1", 1]]) }); // causes error at `save()` stage
// MongoServerError: Updating the path 'nested.$*.map' would create a conflict at 'nested.$*.map'
item.set("nested.inserted2.map", new Map([["a1", 1]])); // does not work at all
Steps to Reproduce
Repro script:
"use strict";
import mongoose from "mongoose";
console.log("Mongoose version", mongoose.version);
await mongoose.connect("mongodb://127.0.0.1:27017/mongoose_test");
await mongoose.connection.dropDatabase();
const MetaSchema = new mongoose.Schema({
items: {
type: Map,
of: new mongoose.Schema(
{
field: { type: String, required: true },
arr: { type: [Number] },
},
{ _id: false }
),
default: new Map(),
},
nested: {
type: Map,
of: new mongoose.Schema(
{
map: {
type: Map,
of: Number,
required: true,
},
},
{ _id: false }
),
default: new Map(),
},
});
const MetaModel = mongoose.model("MetaModel", MetaSchema);
await MetaModel.create({
items: new Map([
["m1", { field: "field1", arr: [1, 2] }],
["m2", { field: "field2", arr: [] }],
]),
nested: new Map([
[
"key",
{
map: new Map([
["k7", 7],
["k8", 8],
["k9", 9],
]),
},
],
[
"key2",
{
map: new Map([["k7", 7]]),
},
],
]),
});
const item = await MetaModel.findOne();
console.log("item", item);
item.set("items.m1.field", "changed");
item.set("items.m2.field", "replaced");
item.set("items.m2.arr", [1]);
item.set("items.m3", { field: "field3", arr: [4] });
item.set("nested.inserted", { map: new Map([["a1", 1]]) });
item.set("nested.inserted2.map", new Map([["a1", 1]]));
console.log(item.modifiedPaths());
console.log(item);
await item.save();
process.exit(0);
output:
Mongoose version 8.15.1
item {
_id: new ObjectId('68400944e3a759c9f5472135'),
items: Map(2) {
'm1' => { field: 'field1', arr: [Array] },
'm2' => { field: 'field2', arr: [] }
},
nested: Map(2) { 'key' => { map: [Map] }, 'key2' => { map: [Map] } },
__v: 0
}
[
'items',
'items.$*',
'items.$*.field',
'items.$*.arr',
'items.m3',
'nested',
'nested.$*',
'nested.$*.map',
'nested.$*.map.a1',
'nested.inserted'
]
{
_id: new ObjectId('68400944e3a759c9f5472135'),
items: Map(3) {
'm1' => { field: 'field1', arr: [Array] },
'm2' => { field: 'field2', arr: [] },
'm3' => { field: 'field3', arr: [Array] }
},
nested: Map(3) {
'key' => { map: [Map] },
'key2' => { map: [Map] },
'inserted' => { map: [Map] }
},
__v: 0
}
/Users/holem/Documents/github/mongoose-map-test/node_modules/mongodb/lib/operations/update.js:75
throw new error_1.MongoServerError(res.writeErrors[0]);
^
MongoServerError: Updating the path 'nested.$*.map' would create a conflict at 'nested.$*.map'
at UpdateOneOperation.execute (/Users/holem/Documents/github/mongoose-map-test/node_modules/mongodb/lib/operations/update.js:75:19)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async tryOperation (/Users/holem/Documents/github/mongoose-map-test/node_modules/mongodb/lib/operations/execute_operation.js:207:20)
at async executeOperation (/Users/holem/Documents/github/mongoose-map-test/node_modules/mongodb/lib/operations/execute_operation.js:75:16)
at async Collection.updateOne (/Users/holem/Documents/github/mongoose-map-test/node_modules/mongodb/lib/collection.js:207:16) {
errorLabelSet: Set(0) {},
errorResponse: {
index: 0,
code: 40,
errmsg: "Updating the path 'nested.$*.map' would create a conflict at 'nested.$*.map'"
},
index: 0,
code: 40
}
Node.js v22.15.0
Expected Behavior
It would be great if model.set()
would work with nested Schema
s and with nested fields in these Schema
s of any supported types (including Map
s).