假设我们有一个名为“images”的MongoDB集合,以及一个带有相应“Image”模型的MongoMapper驱动的应用程序。如果我们使用此模型设置MongoMapper查询,我们会看到它是Plucky::Query
类型并返回类型为Image
的结果:
>> Image.where(:file_type => 'image/jpeg').class
=> Plucky::Query
>> Image.where(:file_type => 'image/jpeg').first.class
=> Image
我们可以通过访问MongoMapper.connection
直接在Mongo适配器上运行相应的查询,主要是绕过MongoMapper。如果我们这样做,查询的类型为Mongo::Cursor
,并返回类型为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
的解决方案,它确实需要Plucky::Query
并返回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(特别是命名范围)的功能来构建查询,所以我最终得到的是{ {1}}。但后来我希望结果是普通的数据对象,而不是模型,因为我需要的只是数据,而且我不想要模型实例化的开销。
答案 0 :(得分:1)
MongoMapper通过在plucky查询上设置“transformer”lambda来实现转换。您可以在MongoMapper source code:
中看到这一点def query(options={})
query = Plucky::Query.new(collection, :transformer => transformer)
...
end
...
def transformer
@transformer ||= lambda { |doc| load(doc) }
end
因此,在每次mongo文档检索之后,这个Plucky::Query
运行加载模型的转换。查看Plucky source code,我们看到有一个简单的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
答案 1 :(得分:1)
如果您放入驱动程序,默认情况下转换器为nil
:
1.9.3p194 :003 > Image.collection.find({ :file_type => 'image/jpeg' }, { :limit => 1 }).first.class
=> BSON::OrderedHash