1

假设我们有一个名为“images”的 MongoDB 集合,以及一个具有相应“Image”模型的 MongoMapper 驱动的应用程序。如果我们使用此模型设置 MongoMapper 查询,我们会看到它是 typePlucky::Query并返回 type 的结果Image

>> Image.where(:file_type => 'image/jpeg').class
=> Plucky::Query

>> Image.where(:file_type => 'image/jpeg').first.class
=> Image

我们可以直接在 Mongo 适配器上运行相应的查询,主要绕过 MongoMapper,通过访问MongoMapper.connection. 如果我们这样做,查询是 typeMongo::Cursor并返回 type 的原始数据结果BSON::OrderedHash

>> MongoMapper.connection.db(dbname).collection('images').find({ :file_type => 'image/jpeg' }).class
=> Mongo::Cursor

>> MongoMapper.connection.db(dbname).collection('images').find({ :file_type => 'image/jpeg' }).first.class
=> BSON::OrderedHash

问题是,有没有办法将Plucky::Query上面的类似内容转换为(或从中检索)一个基本的非扩展Mongo::Cursor对象?

起初我以为我找到了一个解决方案find_each,它实际上需要 aPlucky::Query并返回 a Mongo::Cursor

>> Image.where(:file_type => 'image/jpeg').find_each.class
=> Mongo::Cursor

但事实证明,这Mongo::Cursor以某种方式扩展或与上述不同,因为它仍然返回Image对象而不是BSON::OrderHash对象:

>> Image.where(:file_type => 'image/jpeg').find_each.first.class
=> Image

更新:我不能像在第二种情况下那样完全绕过 MongoMapper 查询魔术,因为我需要访问 MongoMapper 的功能(特别是命名范围)来构建查询,所以我最终得到的是Plucky::Query. 但是我希望结果是纯数据对象,而不是模型,因为我需要的只是数据,我不想要模型实例化的开销。

4

2 回答 2

1

MongoMapper 通过在 plucky 查询上设置一个“transformer”lambda 来实现转换。您可以在MongoMapper 源代码中看到这一点:

def query(options={})
    query = Plucky::Query.new(collection, :transformer => transformer)
    ...
end

...

def transformer
    @transformer ||= lambda { |doc| load(doc) }
end

因此,在每次 mongo 文档检索之后,它Plucky::Query都会运行加载模型的转换。查看Plucky 源代码,我们看到有一个简单的 setter 方法[]可以用来禁用它。所以这是解决方案:

plucky_query = Image.where(:file_type => 'image/jpeg')

plucky_query.first.class
# => Image

plucky_query[:transformer] = nil
plucky_query.first.class
# => BSON::OrderedHash

如果你不介意猴子补丁,你可以像这样封装:

module Plucky
    class Query
        def raw_data
            self[:transformer] = nil
            self
        end
    end
end

然后你可以简单地写:

Image.where(:file_type => 'image/jpeg').raw_data.first.class
# => BSON::OrderedHash
于 2013-02-27T21:05:52.870 回答
1

如果你掉到驱动,变压器nil默认是:

1.9.3p194 :003 > Image.collection.find({ :file_type => 'image/jpeg' }, { :limit => 1 }).first.class
 => BSON::OrderedHash 
于 2013-02-27T21:10:11.113 回答