如何返回mongodb文档直接到客户端,使用Rails和Mongoid



给定文档的日期时间和数据要显示在一个图形中,我怎么能直接返回查询结果,而不从BSON转换到Ruby,然后最后到JSON?

问题:时间值在BSON中为客户端正确存储,但有Ruby参与将其转换为时间对象,我必须做time.to_i * 1000才能在返回的JSON中正确存储。在任何情况下,我都不需要转换任何数据,所以这感觉像是浪费。

我在Heroku + mongoq上运行Rails, Mongoid。我想让Rails应用程序对查询进行授权,但不将响应转换为Ruby对象。

def show_graph
  raw_bson = TheModel.all_raw_documents_matching(query_params)
  raw_bson.to_json  
  # Alternatively, this BSON to JSON could be happening client side. 
  # side. Whatever, just don't convert to ruby objects...
end

你的问题有很多观点。比起BSON反序列化,我看到to_json方法如何处理DateTime ruby对象的序列化更为关键。

我想到的最简单,最棘手的方法是覆盖Time类的as_json方法:

class Time
 def as_json(options={})
    self.to_i * 1000
 end
end
hash = {:time => Time.now}
hash.to_json # "{"a":1367329412000}" 

可以放在初始化器中。这是一个非常简单的解决方案,但是你必须记住,你的应用程序中的每个ruby Time对象将被你的自定义方法序列化。这可能很好,也可能不好,这真的很难说,一些gem可能依赖于此,也可能不依赖于此。

更安全的方法是编写一个包装器并调用它,而不是to_json:

def to_json_with_time
  converted_hash = self.attributes.map{|k,v| {k => v.to_i * 1000 if v.is_a?(Time)} }.reduce(:merge)
  converted_hash.to_json
end

最后,如果你真的想重写Mongoid序列化和反序列化对象的方式,如果你想跳过BSON过程,你必须定义mongoizedemongoize方法。您可以在这里找到文档:自定义字段序列化

* *更新* *

问题是序列化而不是反序列化。如果您从查询中获得原始BSON,您仍然拥有Time ruby对象的字符串表示形式。你不能直接将BSON转换为JSON,因为如果不从ruby Time类传递,就不可能将时间的字符串表示转换为整数表示。

下面是一个如何使用Mongoid自定义字段序列化的示例。

class Foo
  include Mongoid::Document
  field :bar, type: Time
end

class Time
  # The instance method mongoize take an instance of your object, and converts it into how it will be stored in the database
  def mongoize
    self.to_i * 1000
  end
  # The class method mongoize takes an object that you would use to set on your model from your application code, and create the object as it would be stored in the database
  def self.mongoize(o)
    o.mongoize
  end
  # The class method demongoize takes an object as how it was stored in the database, and is responsible for instantiating an object of your custom type.
  def self.demongoize(object)
    object
  end
end
Foo.create(:bar => Time.now) #<Foo _id: 518295cebb9ab4e1d2000006, _type: nil, bar: 1367512526> 
Foo.last.as_json # {"_id"=>"518295cebb9ab4e1d2000006", "bar"=>1367512526} 

相关内容

最新更新