-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
WIP: Map type #6287
WIP: Map type #6287
Conversation
@vkarpov15 I haven't used Maps yet, but I'm going to see if I can wrap my head around them (specifically with respect to mongoose) in the next day or so. I've been reading about them but I have a ways to go before I can add much value to the conversation. I'll be watching for sure, and if there's anything you think I can do to help just say the word. |
@lineus the particular details of maps are interesting but I think the biggest win here is that we can support objects with arbitrary keys. So: const TestSchema = new mongoose.Schema({
myMap: {
type: Map,
of: Number
}
}); Would mean that |
This feature was implemented in version 5.1.0 but still appears to be unavailable as of 5.2.3. Am I missing something? Edit: Turns out I was using the wrong command ( |
@simonrichard it should be available. Can you open an issue with a complete code sample? Or if you'd rather, join us in either Gitter.im or Slack. |
Can Map of ObjectIds be populated? const SomeSchema = new mongoose.Schema({
myMap: {
type: Map,
of: {
type: ObjectId,
ref: 'SomeRef'
}
});
const SomeModel = mongoose.model('SomeModel', SomeSchema);
const populatedDoc = await SomeModel.findOne({...}).populate('myMap').exec(); Now it does not seem to work. Workaround for this is simple, but it would be awesome to have this feature. |
@3lo1i yeah it can be populated, the below script prints 'foo' as expected in Mongoose 5.4.2: const assert = require('assert');
const mongoose = require('mongoose');
mongoose.set('debug', true);
const GITHUB_ISSUE = `gh6287`;
const connectionString = `mongodb://localhost:27017/${ GITHUB_ISSUE }`;
const { Schema } = mongoose;
run().then(() => console.log('done')).catch(error => console.error(error.stack));
async function run() {
await mongoose.connect(connectionString);
await mongoose.connection.dropDatabase();
const SomeSchema = new mongoose.Schema({
myMap: {
type: Map,
of: {
type: mongoose.ObjectId,
ref: 'SomeRef'
}
}
});
const SomeModel = mongoose.model('SomeModel', SomeSchema);
const SomeRef = mongoose.model('SomeRef', new Schema({ name: String }));
const doc1 = await SomeRef.create({ name: 'foo' });
const doc2 = await SomeModel.create({ myMap: { test: doc1._id } });
const populatedDoc = await SomeModel.findOne({}).populate('myMap').exec();
console.log(populatedDoc.myMap.get('test').name); // foo
} |
Re: #681, #4353, and several other issues, we're planning on adding a Map type that builds on ES6 maps. There's some more work for this PR already in the 5.1 branch in f828de3.
The primary motivation for maps is to support arbitrary keys while retaining change tracking and validation. Proxies would be an alternative implementation, but I'm not confident we could implement a pure proxy solution in a reasonable time frame. As a consequence, users will have to use
Map.prototype.get()
to get keys andMap.prototype.set()
to set keys, which makes change tracking much easier but adds some overhead. However, devs that use maps should already be used to this syntax, so mongoose maps will feel familiar.There's a noteworthy caveat that, under the hood, maps become objects when they're stored in MongoDB because there's no notion of a map type in BSON.
Still lots of work to be done to make sure maps work right with queries. @varunjayaraman @lineus I would love to hear your thoughts.
Here's a sample usage from the test case: