假设我在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文档中找不到任何支持地图的内容。
答案 0 :(得分:3)
首先澄清一下。虽然JavaScript规范没有说明一个对象"必须"保留密钥的顺序,几乎每个实现实际上都将密钥顺序保留在标准对象上。
对于MongoDB文档,从技术上讲,它没有在那里记录,因为订单的实际保留因此是 BSON 规范,其中的顺序保证。 BSON实际上并不局限于MongoDB。
至于实际问题,让我们看一下使用BSON serializer的内部函数的代码:
} else if(object instanceof Map) { //<-- Actually looks for the type and handles it
var iterator = object.entries();
var done = false;
while(!done) {
在列表中依此类推,它基本上迭代了Map
中的每个条目,然后使每个成员受到相同的测试条件和分支(不完全是最干的代码),就像在一般顶部做的那样等级检查。
然而,这是一个&#34;大&#34;请注意,在文档大小超过其初始分配的情况下,作为存储引擎的MongoDB可能需要在磁盘上重新定位数据。在这样的文件重写下,它可以&#34;可能&#34;有可能因为实际存储在MongoDB中的项目实际上不再是Map
,所以存储文档中的键可以&#34;重新订购。
多年来,有几个问题与内容重新排序有关,尽管大多数已经修复,但至少要意识到这种情况有可能发生,这是不合理的。
从中汲取的重要教训应该是:
对象密钥通常会按照您创建它们的顺序进行序列化,尽管它不是引擎和#34;必须&#34;那个。
序列化为BSON的基本方法是以不同的方式处理Map
,并且正在采取措施以确保维持订单。
自终极&#34;存储&#34;在服务器上使用BSON规范,然后是唯一方式,您真正确保&#34;保证&#34;订购商品带有&#34;数组&#34;。当订单很重要时,这就是你应该经常使用的。
Map&#39>并不是真正用于&#34;有序键&#34;无论如何,我认为main documentation突出了&#34;三巨头&#34;完美:
- 对象有一个原型,因此地图中有默认键。这可以通过使用自ES5以来的map = Object.create(null)来绕过,但很少完成。
- 对象的键是字符串和符号,它们可以是地图的任何值。
- 您可以轻松获取地图的大小,同时必须手动跟踪对象的大小。
他们确实变得有用了。
作为摘要行&#34; MongoDB是否支持Map对象&#34; ?技术上没有,因为BSON没有相应的类型。但是驱动程序会将其正确转换为存储为BSON文档,但当然所有内容都遵循相同的规则。因此,驱动程序和语言支持是&#34;可选&#34;,因为BSON中没有任何内容可以说这是Map
,那么将由实现的代码将数据读入类似的&# 34;散列/地图&#34;存储遵循相同的规则。
如果你因此只是&#34;真的&#34;有兴趣始终保持插入/维护的顺序,然后使用&#34;数组&#34;代替。