module Mongo::QueryCache
Public Class Methods
Execute the block while using the query cache.
@example Execute with the cache.
QueryCache.cache { collection.find }
@return [ Object ] The result of the block.
# File lib/mongo/query_cache.rb, line 45 def cache enabled = enabled? self.enabled = true begin yield ensure self.enabled = enabled end end
Clear the query cache.
@example Clear the cache.
QueryCache.clear
@return [ nil ] Always nil.
# File lib/mongo/query_cache.rb, line 87 def clear Thread.current["[mongo]:query_cache"] = nil end
Clear the section of the query cache storing cursors with results from this namespace.
@param [ String ] namespace The namespace to be cleared, in the format
"database.collection".
@return [ nil ] Always nil.
@api private
# File lib/mongo/query_cache.rb, line 100 def clear_namespace(namespace) cache_table.delete(namespace) # The nil key is where cursors are stored that could potentially read from # multiple collections. This key should be cleared on every write operation # to prevent returning stale data. cache_table.delete(nil) nil end
Set whether the cache is enabled.
@example Set if the cache is enabled.
QueryCache.enabled = true
@param [ true, false ] value The enabled value.
# File lib/mongo/query_cache.rb, line 25 def enabled=(value) Thread.current["[mongo]:query_cache:enabled"] = value end
Is the query cache enabled on the current thread?
@example Is the query cache enabled?
QueryCache.enabled?
@return [ true, false ] If the cache is enabled.
# File lib/mongo/query_cache.rb, line 35 def enabled? !!Thread.current["[mongo]:query_cache:enabled"] end
For the given query options, retrieve a cached cursor that can be used to obtain the correct query results, if one exists in the cache.
@option opts [ String | nil ] namespace The namespace of the query,
in the format "database_name.collection_name".
@option opts [ Array, Hash ] selector The selector passed to the query.
For most queries, this will be a Hash, but for aggregations, this will be an Array representing the aggregation pipeline. May not be nil.
@option opts [ Integer | nil ] skip The skip value of the query. @option opts [ Hash | nil ] sort The order of the query results
(e.g. { name: -1 }).
@option opts [ Integer | nil ] limit The limit value of the query. @option opts [ Hash | nil ] projection The projection of the query
results (e.g. { name: 1 }).
@option opts [ Hash | nil ] collation The collation of the query
(e.g. { "locale" => "fr_CA" }).
@option opts [ Hash | nil ] read_concern The read concern of the query
(e.g. { level: :majority }).
@option opts [ Hash | nil ] read_preference The read preference of
the query (e.g. { mode: :secondary }).
@option opts [ Boolean | nil ] multi_collection Whether the query
results could potentially come from multiple collections. When true, these results will be stored under the nil namespace key and cleared on every write command.
@return [ Mongo::CachingCursor
| nil ] Returns a CachingCursor
if one
exists in the query cache, otherwise returns nil.
@api private
# File lib/mongo/query_cache.rb, line 178 def get(**opts) limit = opts[:limit] _namespace_key = namespace_key(**opts) _cache_key = cache_key(**opts) namespace_hash = cache_table[_namespace_key] return nil unless namespace_hash caching_cursor = namespace_hash[_cache_key] return nil unless caching_cursor caching_cursor_limit = caching_cursor.view.limit # There are two scenarios in which a caching cursor could fulfill the # query: # 1. The query has a limit, and the stored cursor has no limit or # a larger limit. # 2. The query has no limit and the stored cursor has no limit. # # Otherwise, return nil because the stored cursor will not satisfy # the query. if limit && (caching_cursor_limit.nil? || caching_cursor_limit >= limit) caching_cursor elsif limit.nil? && caching_cursor_limit.nil? caching_cursor else nil end end
Store a CachingCursor
instance in the query cache associated with the specified query options.
@param [ Mongo::CachingCursor
] cursor The CachingCursor
instance to store.
@option opts [ String | nil ] namespace The namespace of the query,
in the format "database_name.collection_name".
@option opts [ Array, Hash ] selector The selector passed to the query.
For most queries, this will be a Hash, but for aggregations, this will be an Array representing the aggregation pipeline. May not be nil.
@option opts [ Integer | nil ] skip The skip value of the query. @option opts [ Hash | nil ] sort The order of the query results
(e.g. { name: -1 }).
@option opts [ Integer | nil ] limit The limit value of the query. @option opts [ Hash | nil ] projection The projection of the query
results (e.g. { name: 1 }).
@option opts [ Hash | nil ] collation The collation of the query
(e.g. { "locale" => "fr_CA" }).
@option opts [ Hash | nil ] read_concern The read concern of the query
(e.g. { level: :majority }).
@option opts [ Hash | nil ] read_preference The read preference of
the query (e.g. { mode: :secondary }).
@option opts [ Boolean | nil ] multi_collection Whether the query
results could potentially come from multiple collections. When true, these results will be stored under the nil namespace key and cleared on every write command.
@return [ true ] Always true.
@api private
# File lib/mongo/query_cache.rb, line 139 def set(cursor, **opts) _cache_key = cache_key(**opts) _namespace_key = namespace_key(**opts) cache_table[_namespace_key] ||= {} cache_table[_namespace_key][_cache_key] = cursor true end
Execute the block with the query cache disabled.
@example Execute without the cache.
QueryCache.uncached { collection.find }
@return [ Object ] The result of the block.
# File lib/mongo/query_cache.rb, line 61 def uncached enabled = enabled? self.enabled = false begin yield ensure self.enabled = enabled end end
Private Class Methods
# File lib/mongo/query_cache.rb, line 210 def cache_key(**opts) unless opts[:namespace] raise ArgumentError.new("Cannot generate cache key without namespace") end unless opts[:selector] raise ArgumentError.new("Cannot generate cache key without selector") end [ opts[:namespace], opts[:selector], opts[:skip], opts[:sort], opts[:projection], opts[:collation], opts[:read_concern], opts[:read_preference] ] end
Get the cached queries.
@example Get the cached queries from the current thread.
QueryCache.cache_table
@return [ Hash ] The hash of cached queries.
# File lib/mongo/query_cache.rb, line 77 def cache_table Thread.current["[mongo]:query_cache"] ||= {} end
If the cached results can come from multiple collections, store this cursor under the nil namespace to be cleared on every write operation. Otherwise, store it under the specified namespace.
# File lib/mongo/query_cache.rb, line 233 def namespace_key(**opts) if opts[:multi_collection] nil else opts[:namespace] end end