Как получить необработанные результаты данных Mongo из объекта MongoMapper Plucky::Query?

Допустим, у нас есть коллекция MongoDB под названием «изображения» и приложение на базе MongoMapper с соответствующей моделью «Изображение». Если мы настроим запрос MongoMapper, используя эту модель, мы увидим, что он имеет тип Plucky::Query и возвращает результаты типа Image:

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

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

Мы можем запустить соответствующий запрос непосредственно на адаптере Mongo, в основном в обход MongoMapper, обратившись к файлу MongoMapper.connection. Если мы сделаем это таким образом, запрос будет типа 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 (конкретно названным областям) для создания запроса, поэтому в итоге я получаю Plucky::Query. Но тогда я хочу, чтобы результаты были простыми объектами данных, а не моделями, потому что все, что мне нужно, это данные, и мне не нужны накладные расходы на создание экземпляра модели.


person Ben Lee    schedule 27.02.2013    source источник


Ответы (2)


Если вы перейдете к драйверу, трансформатор по умолчанию nil:

1.9.3p194 :003 > Image.collection.find({ :file_type => 'image/jpeg' }, { :limit => 1 }).first.class
 => BSON::OrderedHash 
person slowernet    schedule 27.02.2013
comment
Спасибо, но в моем случае это не сработает, потому что я хочу использовать функции MongoMapper для создания исходного запроса. Я обновляю свой вопрос, чтобы уточнить этот момент. - person Ben Lee; 28.02.2013

MongoMapper выполняет преобразование, устанавливая лямбду-трансформер в смелом запросе. Вы можете увидеть это в исходном коде MongoMapper. :

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

...

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

Таким образом, после каждого извлечения документа монго этот Plucky::Query запускает преобразование, которое загружает модель. Глядя на исходный код Plucky, мы видим, что простой метод установки [] мы можем использовать, чтобы отключить это. Итак, это решение:

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
person Ben Lee    schedule 27.02.2013