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.13.2
Node.js version
23.11.0
MongoDB server version
8.0.8
Typescript version (if applicable)
No response
Description
The document contains a field of type Map
, where the values are arrays of something (e.g., numbers). If you do doc.map.get(key)
, modify the array (e.g., by adding a new value), and then call set(key)
, Mongoose generates an incorrect query for MongoDB.
However, if you do the same thing but recreate the array after get(key)
(e.g., [...doc.map.get(key)]
), then Mongoose generates the correct query for MongoDB.
Steps to Reproduce
"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();
mongoose.set("debug", true);
const DocSchema = new mongoose.Schema({
map: {
type: Map,
of: [{ type: Number }],
default: new Map(),
},
});
const Doc = mongoose.model("Doc", DocSchema);
const doc = await Doc.create({});
console.log("just created", doc);
doc.map.set("key", [1, 2]);
await doc.save();
console.log("key set", doc);
const list = doc.map.get("key");
// const list = [...doc.map.get("key")];
list.push(3);
doc.map.set("key", list);
await doc.save();
console.log("key get/push/set", doc);
const userLoaded = await Doc.findById(doc._id.toString());
console.log("from db", userLoaded);
Incorrect case (const list = doc.map.get("key");
):
Mongoose version 8.13.2
Mongoose: docs.insertOne({ map: Map(0) {}, _id: ObjectId("67fac37873021776275453b0"), __v: 0 }, {})
just created {
map: Map(0) {},
_id: new ObjectId('67fac37873021776275453b0'),
__v: 0
}
Mongoose: docs.updateOne({ _id: ObjectId("67fac37873021776275453b0"), __v: 0 }, { '$set': { 'map.key': [ 1, 2 ] }, '$inc': { __v: 1 } }, {})
key set {
map: Map(1) { 'key' => [ 1, 2 ] },
_id: new ObjectId('67fac37873021776275453b0'),
__v: 1
}
Mongoose: docs.updateOne({ _id: ObjectId("67fac37873021776275453b0") }, { '$set': { 'map.$*': Map(1) { 'key' => [ 1, 2, 3 ] } }}, {})
key get/push/set {
map: Map(1) { 'key' => [ 1, 2, 3 ] },
_id: new ObjectId('67fac37873021776275453b0'),
__v: 1
}
Mongoose: docs.findOne({ _id: ObjectId("67fac37873021776275453b0") }, {})
from db { _id: new ObjectId('67fac37873021776275453b0'), __v: 1 }
Correct case (const list = [...doc.map.get("key")];
):
Mongoose version 8.13.2
Mongoose: docs.insertOne({ map: Map(0) {}, _id: ObjectId("67fac4c4564026e97c390825"), __v: 0 }, {})
just created {
map: Map(0) {},
_id: new ObjectId('67fac4c4564026e97c390825'),
__v: 0
}
Mongoose: docs.updateOne({ _id: ObjectId("67fac4c4564026e97c390825"), __v: 0 }, { '$set': { 'map.key': [ 1, 2 ] }, '$inc': { __v: 1 } }, {})
key set {
map: Map(1) { 'key' => [ 1, 2 ] },
_id: new ObjectId('67fac4c4564026e97c390825'),
__v: 1
}
Mongoose: docs.updateOne({ _id: ObjectId("67fac4c4564026e97c390825"), __v: 1 }, { '$set': { 'map.key': [ 1, 2, 3 ] }, '$inc': { __v: 1 } }, {})
key get/push/set {
map: Map(1) { 'key' => [ 1, 2, 3 ] },
_id: new ObjectId('67fac4c4564026e97c390825'),
__v: 2
}
Mongoose: docs.findOne({ _id: ObjectId("67fac4c4564026e97c390825") }, {})
from db {
_id: new ObjectId('67fac4c4564026e97c390825'),
map: Map(1) { 'key' => [ 1, 2, 3 ] },
__v: 2
}
Difference in 3rd query - docs.updateOne
:
incorrect - ... '$set': { 'map.$*': Map(1) { 'key' => [ 1, 2, 3 ] } ...
correct - ... '$set': { 'map.key': [ 1, 2, 3 ] } ...
Expected Behavior
Mongoose should generate correct queries to MongoDB in both cases.