mongoid query caching

后端 未结 4 1888
忘掉有多难
忘掉有多难 2020-12-28 18:38

Rails\' ActiveRecord has a feature called Query Caching (ActiveRecord::QueryCache) which saves the result of SQL query for the life-span of a request. While I\'m not very fa

4条回答
  •  既然无缘
    2020-12-28 19:09

    The other answer is obviously wrong. Not only mongoid or mongo driver doesn't cache the query, even if mongo would - it still might be on other machine across the network.

    My solution was to wrap the receive_message in Mongo::Connection. Pros: one definite place Cons: deserialization still takes place

    
    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)
    

提交回复
热议问题