6

Suppose I have a Map of ordered items in a node.js application:

var myMap = new Map();
myMap.set("a", "b");
myMap.set("c", "d");
myMap.set("e", "f");

I then store this map in a database using the MongoDB node.js driver:

collection.insertOne({myMap: myMap});

The stored map looks like:

{ "myMap" : { "a" : "b", "c" : "d", "e" : "f" } }

I know that a Map's order is guaranteed, but is it guaranteed to be stored in MongoDB in that order? And is it guaranteed to be read from MongoDB in that order?

It's a pretty simple question, but I couldn't find anything in the MongoDB documentation about it supporting Maps.

SilentByte
  • 1,098
  • 1
  • 10
  • 21
  • Sorry I flagged this question as "needs improvement". Because I think this question should be "Does Map in MongoDB guarantee insertion order?" with javascript, node or something. And sorry I cannot suggest edit so I can only put here. If this question get corrected pls remind me for removing this comment. – TeaDrinker Mar 29 '23 at 09:22

1 Answers1

5

First a clarify. Though the JavaScript spec does not say that an object "must" retain the order of keys, just about every implementation actually keeps the key order on standard objects anyway.

As for MongoDB documentation, then technically it is not documented there because the actual retention of order is therefore a BSON spec where the order of keys is guaranteed. And BSON is not actually restricted to MongoDB.

As for the actual question, let's look at the code from the from the inner functions of the BSON serializer used:

  } else if(object instanceof Map) {    //<-- Actually looks for the type and handles it
    var iterator = object.entries();
    var done = false;

    while(!done) {

And so on in the listing, which is basically iterating each entry in the Map and then subjects each member to the same test conditions and branching ( not exactly the most DRY code ) as would be done on general top level inspection.

Thre is however one "big" note on this, which is that MongoDB as a storage engine may need to re-locate data on disk in cases where the document size outgrows its initial allocation. Under such document re-writes, it "may" be possible that since the items actually stored in MongoDB are no longer actually a Map, that the keys in the stored document "may" become re-ordered.

There have been several issues raised over the years related to content re-ordering, and though most have been fixed, it would not be un-reasonable to at least be aware that this has a possibility of happening.

The big lesson to take away from this should really be that:

  1. Object keys are generally going to be serialized in the order you created them anyway, despite it not being a hard specification that engines "must" to that.

  2. The underlying method of serializing to BSON is treating Map differently, and is going out of it's way to make sure the order is maintained.

  3. Since ultimate "storage" lies with the BSON spec on the server, then the only way you truly "assure" ordered items is with an "array". And that is really what you should always use when order is important.

Map's are not really implemented just for "ordered keys" anyway, and I think the main documentation highlights the "big three" perfectly:

  • An Object has a prototype, so there are default keys in the map. This could be bypassed by using map = Object.create(null) since ES5, but was seldomly done.
  • The keys of an Object are Strings and Symbols, where they can be any value for a Map.
  • You can get the size of a Map easily while you have to manually keep track of size for an Object.

That's were they really do become useful.

As a summary line "Does MongoDB support Map objects"? Tecnically No, since there is no corresponding type for BSON. But the driver will convert it correctly to store as a BSON document, but of course everything is subject to the same rule applied there. Driver and language support is therefore "optional", since there is nothing in the BSON to say this is a Map, then it would be up to the implemented code to read the data into similar "Hash/Map" storage that followed the same rules.

If you are therefore only "really" interested in always maintaining order of insertion/maintenance, then use an "array" instead.

Blakes Seven
  • 49,422
  • 14
  • 129
  • 135
  • 1
    "Though the JavaScript spec does not say that an object "must" retain the order of keys" --- it kinda does http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys – zerkms Mar 20 '16 at 22:57
  • @zerkms Not really the main point here anyway. It's just how people "perceive" the spec, and therefore difference between `Map` and `Object`.Somewhat ambigious, but the real meat here is in the BSON treatment. I do note that the `Map` documentation deliberately makes no such distinction. – Blakes Seven Mar 20 '16 at 23:00
  • I agree with your answer (and the only upvote it currently has is mine), and my point was that it's not technically correct to state that the specification does not have something while it does. – zerkms Mar 20 '16 at 23:02
  • @zerkms And I'm not arguing. But I am being realistic that 9/10 people ( or at least those who find this topic ) are likely to have viewed or will view [Does JavaScript Guarantee Object Property Order](http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order) and most of those probably jumped to conclude *"I'll use Map then!"*. So whilst recent literature may differ in explanation, the historic message is out there. Plus we are telling people *"It's just ordered anyway"* as well as the ultimate thing to do when "order" is of utmost importance. – Blakes Seven Mar 20 '16 at 23:22