文档菜单
文档首页
/ / /
Ruby MongoDB 驱动程序
/

查询缓存

在本页面上

  • 用法
  • 与纤维的交互
  • 查询匹配
  • 限制
  • 缓存失效
  • 手动缓存失效
  • 事务
  • 聚合
  • 系统集合
  • 查询缓存中间件
  • Rack 中间件
  • Active Job 中间件

MongoDB Ruby 驱动程序提供了一个内置的查询缓存。当启用时,查询缓存会保存之前执行的 find 和聚合查询的结果。当再次执行相同的查询时,驱动程序会返回缓存的查询结果,以防止不必要的数据库往返。

查询缓存默认是禁用的。它可以在全局范围内以及特定块上下文中启用。驱动程序还提供了一个Rack 中间件来自动为每个网络请求启用查询缓存。

要全局启用查询缓存

Mongo::QueryCache.enabled = true

同样,要全局禁用它

Mongo::QueryCache.enabled = false

要在块上下文中启用查询缓存

Mongo::QueryCache.cache do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
client['artists'].find(name: 'Flying Lotus').first
#=> Queries the database and caches the result
client['artists'].find(name: 'Flying Lotus').first
#=> Returns the previously cached result
end
end

并在块上下文中禁用查询缓存

Mongo::QueryCache.uncached do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
client['artists'].find(name: 'Flying Lotus').first
#=> Sends the query to the database; does NOT cache the result
client['artists'].find(name: 'Flying Lotus').first
#=> Queries the database again
end
end

您可以通过调用Mongo::QueryCache.enabled?来检查查询缓存是否启用,这将返回 truefalse

查询缓存启用标志存储在纤维本地存储中(使用 Thread.current)。从原则上讲,这允许查询缓存状态是针对每个纤维的,尽管目前尚未进行测试。

Ruby标准库中存在一些方法,例如Enumerable#next,它们的实现中使用纤维。当应用程序设置查询缓存启用标志时,这些方法不会看到它,并且不会使用查询缓存。例如,以下代码即使请求了查询缓存,也没有使用它:

Mongo::QueryCache.enabled = true
client['artists'].find({}, limit: 1).to_enum.next
# Issues the query again.
client['artists'].find({}, limit: 1).to_enum.next

将此代码重写为使用first而不是next将使其使用查询缓存

Mongo::QueryCache.enabled = true
client['artists'].find({}, limit: 1).first
# Utilizes the cached result from the first query.
client['artists'].find({}, limit: 1).first

如果查询与产生缓存结果的原查询匹配,则可以使用缓存结果。以下值相同的两个查询被视为匹配:

  • 命名空间(执行查询的数据库和集合)

  • 选择器(对于聚合,聚合管道阶段)

  • 跳过

  • 排序

  • 投影

  • 排序规则

  • 读取关注点

  • 读取偏好

例如,如果您执行了一个查询,然后执行了一个与排序顺序不同的类似查询,这些查询将不会被视作匹配,第二个查询将不会使用第一个查询的缓存结果。

执行带限制的查询时,如果存在具有较大限制的现有缓存查询,查询缓存将重用该查询。例如

Mongo::QueryCache.cache do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
client['artists'].find(genre: 'Rock', limit: 10)
#=> Queries the database and caches the result
client['artists'].find(genre: 'Rock', limit: 5)
#=> Returns the first 5 results from the cached query
client['artists'].find(genre: 'Rock', limit: 20)
#=> Queries the database again and replaces the previously cached query results
end
end

每次写操作都会部分或全部清除查询缓存。大多数写操作将清除在写入的同一集合上执行的任何查询的结果。某些操作将清除整个查询缓存。

以下操作将在相同数据库和集合上清除缓存查询结果(包括在批量写入期间)

  • insert_one

  • update_one

  • replace_one

  • update_many

  • delete_one

  • delete_many

  • find_one_and_delete

  • find_one_and_update

  • find_one_and_replace

以下操作将清除整个查询缓存

  • 使用 $merge$out 管道阶段的聚合操作

  • 提交事务

  • 中止事务

您可以使用以下方法随时清除查询缓存

Mongo::QueryCache.clear

这将删除所有缓存的查询结果。

查询在事务的上下文中进行缓存,但在提交或中止事务时,整个缓存将被清除。

Mongo::QueryCache.cache do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
session = client.start_session
session.with_transaction do
client['artists'].insert_one({ name: 'Fleet Foxes' }, session: session)
client['artists'].find({}, session: session).first
#=> { name: 'Fleet Foxes' }
#=> Queries the database and caches the result
client['artists'].find({}, session: session).first
#=> { name: 'Fleet Foxes' }
#=> Returns the previously cached result
session.abort_transaction
end
client['artists'].find.first
#=> nil
# The query cache was cleared on abort_transaction
end
end

注意

事务通常与“快照”读取关注级别一起执行。请注意,具有“快照”读取关注级别的查询无法返回没有“快照”读取关注级别的查询的缓存结果,因此事务可能不会使用先前缓存的查询。

要了解查询何时将使用缓存结果,请参阅查询匹配部分。

查询缓存还会缓存聚合管道的结果。例如

Mongo::QueryCache.cache do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
client['artists'].aggregate([ { '$match' => { name: 'Fleet Foxes' } } ]).first
#=> Queries the database and caches the result
client['artists'].aggregate([ { '$match' => { name: 'Fleet Foxes' } } ]).first
#=> Returns the previously cached result
end
end

注意

在每次写入操作期间,都会从缓存中清除聚合结果,没有例外。

MongoDB将系统信息存储在遵循database.system.*命名空间模式的集合中。这些被称为系统集合。

系统集合中的数据可能会由于应用程序(如内部服务器进程)触发的活动以及应用程序发出的各种数据库命令而发生变化。由于难以确定何时应该使系统集合的缓存结果过期,因此对系统集合的查询会绕过查询缓存。

您可以在MongoDB文档中了解更多有关系统集合的信息:MongoDB文档。

注意

即使在查询缓存启用的情况下,系统集合的查询结果也不会被缓存。

驱动程序提供了一种Rack中间件,它可以在每个Web请求期间启用查询缓存。以下是在Ruby on Rails应用程序中启用查询缓存中间件的示例

# config/application.rb
# Add Mongo::QueryCache::Middleware at the bottom of the middleware stack
# or before other middleware that queries MongoDB.
config.middleware.use Mongo::QueryCache::Middleware

请参阅Rails on Rack指南,了解如何在Rails应用程序中使用Rack中间件。

该驱动程序提供了一种Active Job中间件,可以为每个作业启用查询缓存。以下是在Ruby on Rails应用程序中启用查询缓存Active Job中间件的示例:

# config/application.rb
ActiveSupport.on_load(:active_job) do
include Mongo::QueryCache::Middleware::ActiveJob
end

返回

地理空间搜索