Другой ответ явно неправильный. Не только mongoid или mongo драйвер не кэширует запрос, даже если mongo сделает это - он все еще может находиться на другой машине в сети.
Моим решением было обернуть receive_message в Mongo :: Connection.
Плюсы: одно определенное место
Минусы: десериализация все еще происходит
require 'mongo'
module Mongo
class Connection
module QueryCache
extend ActiveSupport::Concern
module InstanceMethods
# Enable the selector cache within the block.
def cache
@query_cache ||= {}
old, @query_cache_enabled = @query_cache_enabled, true
yield
ensure
clear_query_cache
@query_cache_enabled = old
end
# Disable the selector cache within the block.
def uncached
old, @query_cache_enabled = @query_cache_enabled, false
yield
ensure
@query_cache_enabled = old
end
def clear_query_cache
@query_cache.clear
end
def cache_receive_message(operation, message)
@query_cache[operation] ||= {}
key = message.to_s.hash
log = "[MONGO] CACHE %s"
if entry = @query_cache[operation][key]
Mongoid.logger.debug log % 'HIT'
entry
else
Mongoid.logger.debug log % 'MISS'
@query_cache[operation][key] = yield
end
end
def receive_message_with_cache(operation, message, log_message=nil, socket=nil, command=false)
if query_cache_enabled
cache_receive_message(operation, message) do
receive_message_without_cache(operation, message, log_message, socket, command)
end
else
receive_message_without_cache(operation, message, log_message, socket, command)
end
end
end # module InstanceMethods
included do
alias_method_chain :receive_message, :cache
attr_reader :query_cache, :query_cache_enabled
end
end # module QueryCache
end # class Connection
end
Mongo::Connection.send(:include, Mongo::Connection::QueryCache)