MongoDB是否支持Map对象?

假设我有一个node.js应用程序中的有序项目的Map:

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

然后我使用MongoDB node.js驱动程序将这个映射存储在数据库中:

 collection.insertOne({myMap: myMap}); 

存储的地图如下所示:

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

我知道一个Map的顺序是有保证的,但保证按照这个顺序存储在MongoDB中? 这是保证从MongoDB读取顺序?

这是一个非常简单的问题,但我在MongoDB文档中找不到任何关于支持Maps的内容。

首先澄清。 尽pipeJavaScript规范没有说对象“必须”保留键的顺序,但是几乎每个实现实际上都保持了标准对象上的键顺序。

至于MongoDB文档,那么从技术上讲它并没有logging在那里,因为订单的实际保留因此保证密钥顺序的BSON规范。 而BSON实际上并不限于MongoDB。

至于实际的问题,我们来看看来自BSON串行器内部函数的代码:

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

在列表中,基本上迭代Map每个条目,然后使每个成员受到相同的testing条件和分支(不完全是最干的代码),就像在通用顶级检查中所做的那样。

然而,这是一个“大”的说明,这就是说,在文档大小超过其初始分配的情况下,作为存储引擎的MongoDB可能需要重新定位磁盘上的数据。 在这样的文件重写下,“可能”是可能的,因为实际上存储在MongoDB中的项目实际上不再是一个Map ,存储文件中的密钥“可以”被重新sorting。

这些年来,在内容重新sorting方面出现了一些问题,尽pipe大多数问题已经得到解决,但至less要意识到这种情况有可能发生,这是不合理的。

要从中吸取的重大教训应该是:

  1. 对象键通常会按照您创build的顺序进行序列化,尽pipe它并不是引擎“必须”的硬性规范。

  2. 序列化到BSON的底层方法是对待Map不同,并且正在确保订单的维护。

  3. 由于服务器上的BSON规范存在最终的“存储”,因此真正“保证”订购商品的唯一方法是使用“数组”。 当订单很重要时,这就是你应该总是使用的东西。

地图并不是真的只是为了“有序的键”而实现的,我认为主要的文档完美地突出了“三大”:

  • 一个对象有一个原型,所以在地图上有默认的键。 这可以通过自ES5使用map = Object.create(null)来绕过,但很less完成。
  • 对象的关键字是string和符号,它们可以是Map的任何值。
  • 您可以轻松获取地图的大小,而您必须手动跟踪对象的大小。

那就是他们真的变得有用了。

作为“MongoDB支持Map对象”的摘要行吗? Tecnically不,因为BSON没有相应的types。 但驱动程序会正确地将其转换为BSON文件存储,但是当然,所有内容都遵循相同的规则。 因此,驱动程序和语言支持是“可选的”,因为在BSON中没有什么可以说这是一个Map ,那么它将由实现的代码读取数据到类似的“Hash / Map”存储中,遵循相同的规则。

因此,如果您只是“确实”对维护插入/维护顺序感兴趣,那就用一个“数组”来代替。