假设我在 node.js 应用程序中有一个有序项目的映射:
var myMap = new Map();
myMap.set("a", "b");
myMap.set("c", "d");
myMap.set("e", "f");
然后我使用 MongoDB node.js 驱动程序将此 map 存储在数据库中:
collection.insertOne({myMap: myMap});
存储的 map 如下所示:
{ "myMap" : { "a" : "b", "c" : "d", "e" : "f" } }
我知道 Map 的顺序是有保证的,但是它能保证按顺序存储在 MongoDB 中吗?是否保证按该顺序从 MongoDB 读取它?
这是一个非常简单的问题,但我在 MongoDB 文档中找不到任何关于它支持 map 的内容。
最佳答案
首先澄清一下。尽管 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) {
在 list 中依此类推,它基本上是迭代 Map 中的每个条目,然后使每个成员都接受相同的测试条件和分支(不完全是最 DRY 代码)关于一般的顶层检查。
然而,有一个“重要”注意事项,即 MongoDB 作为存储引擎可能需要在文档大小超过其初始分配的情况下重新定位磁盘上的数据。在此类文档重写下,由于实际存储在 MongoDB 中的项目实际上不再是 Map,因此存储文档中的键“可能”“可能”重新排序。
多年来出现了几个与内容重新排序相关的问题,虽然大多数问题都已得到解决,但至少要意识到这有可能发生并不是没有道理的。
从中吸取的重要教训应该是:
对象键通常会按照您创建它们的顺序进行序列化,尽管引擎“必须”这样做并不是硬性规范。
序列化为 BSON 的底层方法以不同方式处理 Map,并且正在竭尽全力确保顺序得到维护。
由于最终的“存储”取决于服务器上的 BSON 规范,因此您真正“确保”订购商品的唯一方式是使用“数组”。当顺序很重要时,这确实是您应该始终使用的。
无论如何,Map 并不是真正为“有序键”实现的,我认为 main documentation完美凸显“三巨头”:
- 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.
那是他们真的变得有用了。
作为总结行 “MongoDB 是否支持 Map 对象”?技术上没有,因为 BSON 没有相应的类型。但是驱动程序会将其正确转换为存储为 BSON 文档,但当然一切都受那里应用的相同规则的约束。因此,驱动程序和语言支持是“可选的”,因为 BSON 中没有任何内容表明这是一个 Map,那么将由实现的代码将数据读入类似的“Hash/Map” "遵循相同规则的存储。
因此,如果您只是“真正”对始终保持插入/维护顺序感兴趣,那么请改用“数组”。
关于javascript - MongoDB 是否支持 Map 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36119442/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案