Rails 的 ActiveRecord 有一个称为查询缓存 (ActiveRecord::QueryCache) 的功能,它可以在请求的生命周期内保存 SQL 查询的结果。虽然我不太熟悉实现的内部结构,但我认为它将查询结果保存在 Rack env 中的某个位置,该结果在请求结束时被丢弃。
不幸的是,Mongoid 目前不提供此类功能,并且某些查询隐式发生(引用)这一事实加剧了这种情况。 我正在考虑实现这个功能,我很好奇,为了实现这个功能,应该在哪里以及如何连接 Mongoid(或者也许是 mongo 驱动程序?)。
http://mongoid.org/en/mongoid/docs/extras.html
MongoDB本身也具有缓存能力:http://www.mongodb.org/display/DOCS/Caching
mongoid 缓存额外知道两种不同的情况:缓存模型的所有查询或缓存查询。Mongoid 缓存的工作方式似乎略有不同:它看起来像 mongoid 委托缓存到 mongodb。 (在 mongoid 的源代码中,我只能找到缓存的选项设置,但找不到缓存模块。)
最后,我想说,一般来说,缓存没有真正的区别——在内存中实际上就是在内存中!无论是在应用程序中还是在数据库中。
我不喜欢实现额外的缓存算法,因为这似乎是多余的并且是 RAM 杀手。
顺便说一句:如果您确实想在应用程序内缓存结果,您可以尝试
Rails.cache
或其他缓存 gem 作为解决方法。
我的解决方案是将 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)
只需在
application.rb
config.middleware.use "Mongoid::QueryCache::Middleware"
然后利润:
MOPED: 127.0.0.1:27017 QUERY database=XXX collection=page_variants selector={"$query"=>{"_id"=>BSON::ObjectId('5564dabb6d61631e21d70000')}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil runtime: 0.4397ms
MOPED: 127.0.0.1:27017 QUERY database=XXX collection=page_variants selector={"$query"=>{"_id"=>BSON::ObjectId('5564dacf6d61631e21dc0000')}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil runtime: 0.4590ms
QUERY CACHE database=XXX collection=page_variants selector={"$query"=>{"_id"=>BSON::ObjectId('5564c9596d61631e21d30000')}, "$orderby"=>{:_id=>1}}
QUERY CACHE database=XXX collection=page_variants selector={"$query"=>{"_id"=>BSON::ObjectId('5564dabb6d61631e21d70000')}, "$orderby"=>{:_id=>1}}
Mongoid 变更日志
https://github.com/mongoid/mongoid/blob/master/CHANGELOG.md#new-features-2
3410 Mongoid 现在有一个查询缓存,可以用作 Rack 应用程序中的中间件。 (阿瑟·内维斯)对于轨道:
config.middleware.use(Mongoid::QueryCache::Middleware)