I think there's still a bug similar to #6478:
What is the current behavior?
When converting a Mongoose document to an object via toObject
, a Map still remains a Map. As from that point on I actually expect to be working with a POJO, this is problematic, especially since I'm converting it to JSON a bit later and will end up with an empty Object instead of a POJO representing my map.
The following, slightly modified script from #6486 should demonstrate the issue:
#!/usr/bin/env node
'use strict';
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
const conn = mongoose.connection;
const Schema = mongoose.Schema;
const Map = global.Map;
const schema = new Schema({
test: {
type: Map,
of: String,
default: new Map()
}
});
const Test = mongoose.model('test', schema);
const mapTest = new Test({});
mapTest.test.set('key1', 'value1');
async function run() {
await conn.dropDatabase();
await mapTest.save();
let found = await Test.findOne();
let pojo = found.toObject();
console.log(JSON.stringify(pojo));
return conn.close();
}
run();
What is the expected behavior?
I'd expect toObject
to map a MongooseMap to a POJO as well.
Please mention your node.js, mongoose and MongoDB version.
Node: v11.1.0
MongoDB: 3.6.5
Thanks for reporting, will fix
If you don't use toObject()
, this works fine:
async function run() {
await conn.dropDatabase();
await mapTest.save();
let found = await Test.findOne();
//let pojo = found.toObject();
console.log(JSON.stringify(found));
console.log(pojo.test)
return conn.close();
}
That's because, in general, we try to make toObject()
not do too much, but toJSON()
actually converts maps to POJOs because JSON.stringify()
doesn't handle maps. In 5.3.15 you'll be able to do this:
async function run() {
await conn.dropDatabase();
await mapTest.save();
let found = await Test.findOne();
let pojo = found.toObject({ flattenMaps: true });
console.log(JSON.stringify(pojo));
console.log(pojo.test)
return conn.close();
}
Wonderful, thanks a lot!
It seems that flattenMaps
can't be used by schema.set('toObject', { flattenMaps: true })
@vkarpov15
@liubog2008 thanks for reporting, I'll reopen this and take a look.
Most helpful comment
If you don't use
toObject()
, this works fine:That's because, in general, we try to make
toObject()
not do too much, buttoJSON()
actually converts maps to POJOs becauseJSON.stringify()
doesn't handle maps. In 5.3.15 you'll be able to do this: