Module: Mongo::QueryCache

Defined in:
lib/mongo/query_cache.rb

Defined Under Namespace

Classes: Middleware

Class Method Summary collapse

Class Method Details

.cacheObject

Execute the block while using the query cache.

Examples:

Execute with the cache.

QueryCache.cache { collection.find }

Returns:

  • (Object)

    The result of the block.



48
49
50
51
52
53
54
55
56
# File 'lib/mongo/query_cache.rb', line 48

def cache
  enabled = enabled?
  self.enabled = true
  begin
    yield
  ensure
    self.enabled = enabled
  end
end

.clearnil

Clear the query cache.

Examples:

Clear the cache.

QueryCache.clear

Returns:

  • (nil)

    Always nil.



90
91
92
# File 'lib/mongo/query_cache.rb', line 90

def clear
  Thread.current["[mongo]:query_cache"] = nil
end

.clear_namespace(namespace) ⇒ nil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Clear the section of the query cache storing cursors with results from this namespace.

Parameters:

  • namespace (String)

    The namespace to be cleared, in the format “database.collection”.

Returns:

  • (nil)

    Always nil.



103
104
105
106
107
108
109
110
# File 'lib/mongo/query_cache.rb', line 103

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

.enabled=(value) ⇒ Object

Set whether the cache is enabled.

Examples:

Set if the cache is enabled.

QueryCache.enabled = true

Parameters:

  • value (true, false)

    The enabled value.



28
29
30
# File 'lib/mongo/query_cache.rb', line 28

def enabled=(value)
  Thread.current["[mongo]:query_cache:enabled"] = value
end

.enabled?true, false

Is the query cache enabled on the current thread?

Examples:

Is the query cache enabled?

QueryCache.enabled?

Returns:

  • (true, false)

    If the cache is enabled.



38
39
40
# File 'lib/mongo/query_cache.rb', line 38

def enabled?
  !!Thread.current["[mongo]:query_cache:enabled"]
end

.get(**opts) ⇒ Mongo::CachingCursor | nil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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.

Parameters:

  • opts (Hash)

    a customizable set of options

Options Hash (**opts):

  • :namespace (String | nil)

    The namespace of the query, in the format “database_name.collection_name”.

  • :selector (Array, Hash)

    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.

  • :skip (Integer | nil)

    The skip value of the query.

  • :sort (Hash | nil)

    The order of the query results (e.g. { name: -1 }).

  • :limit (Integer | nil)

    The limit value of the query.

  • :projection (Hash | nil)

    The projection of the query results (e.g. { name: 1 }).

  • :collation (Hash | nil)

    The collation of the query (e.g. { “locale” => “fr_CA” }).

  • :read_concern (Hash | nil)

    The read concern of the query (e.g. { level: :majority }).

  • :read_preference (Hash | nil)

    The read preference of the query (e.g. { mode: :secondary }).

  • :multi_collection (Boolean | nil)

    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.

Returns:

  • (Mongo::CachingCursor | nil)

    Returns a CachingCursor if one exists in the query cache, otherwise returns nil.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/mongo/query_cache.rb', line 181

def get(**opts)
  limit = normalized_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 = normalized_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

.normalized_limit(limit) ⇒ Object



213
214
215
216
217
218
219
# File 'lib/mongo/query_cache.rb', line 213

def normalized_limit(limit)
  return nil unless limit
  # For the purposes of caching, a limit of 0 means no limit, as mongo treats it as such.
  return nil if limit == 0
  # For the purposes of caching, a negative limit is the same as as a positive limit.
  limit.abs
end

.set(cursor, **opts) ⇒ true

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Store a CachingCursor instance in the query cache associated with the specified query options.

Parameters:

  • cursor (Mongo::CachingCursor)

    The CachingCursor instance to store.

  • opts (Hash)

    a customizable set of options

Options Hash (**opts):

  • :namespace (String | nil)

    The namespace of the query, in the format “database_name.collection_name”.

  • :selector (Array, Hash)

    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.

  • :skip (Integer | nil)

    The skip value of the query.

  • :sort (Hash | nil)

    The order of the query results (e.g. { name: -1 }).

  • :limit (Integer | nil)

    The limit value of the query.

  • :projection (Hash | nil)

    The projection of the query results (e.g. { name: 1 }).

  • :collation (Hash | nil)

    The collation of the query (e.g. { “locale” => “fr_CA” }).

  • :read_concern (Hash | nil)

    The read concern of the query (e.g. { level: :majority }).

  • :read_preference (Hash | nil)

    The read preference of the query (e.g. { mode: :secondary }).

  • :multi_collection (Boolean | nil)

    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.

Returns:

  • (true)

    Always true.



142
143
144
145
146
147
148
149
150
# File 'lib/mongo/query_cache.rb', line 142

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

.uncachedObject

Execute the block with the query cache disabled.

Examples:

Execute without the cache.

QueryCache.uncached { collection.find }

Returns:

  • (Object)

    The result of the block.



64
65
66
67
68
69
70
71
72
# File 'lib/mongo/query_cache.rb', line 64

def uncached
  enabled = enabled?
  self.enabled = false
  begin
    yield
  ensure
    self.enabled = enabled
  end
end