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要意识到这种情况有可能发生,这是不合理的。
要从中吸取的重大教训应该是:
-
对象键通常会按照您创build的顺序进行序列化,尽pipe它并不是引擎“必须”的硬性规范。
-
序列化到BSON的底层方法是对待
Map
不同,并且正在确保订单的维护。 -
由于服务器上的BSON规范存在最终的“存储”,因此真正“保证”订购商品的唯一方法是使用“数组”。 当订单很重要时,这就是你应该总是使用的东西。
地图并不是真的只是为了“有序的键”而实现的,我认为主要的文档完美地突出了“三大”:
- 一个对象有一个原型,所以在地图上有默认的键。 这可以通过自ES5使用map = Object.create(null)来绕过,但很less完成。
- 对象的关键字是string和符号,它们可以是Map的任何值。
- 您可以轻松获取地图的大小,而您必须手动跟踪对象的大小。
那就是他们真的变得有用了。
作为“MongoDB支持Map对象”的摘要行吗? Tecnically不,因为BSON没有相应的types。 但驱动程序会正确地将其转换为BSON文件存储,但是当然,所有内容都遵循相同的规则。 因此,驱动程序和语言支持是“可选的”,因为在BSON中没有什么可以说这是一个Map
,那么它将由实现的代码读取数据到类似的“Hash / Map”存储中,遵循相同的规则。
因此,如果您只是“确实”对维护插入/维护顺序感兴趣,那就用一个“数组”来代替。