新手问题 mongoid 缓存

whatisruby · 2012年09月05日 · 最后由 whatisruby 回复于 2012年09月05日 · 3480 次阅读

两张表,大概结构是

Reply
  belongs_to :topic, :inverse_of => :replies

Topic
  has_many :replies

有一个 id=1 的 topic,同时有一个 id=1 的 reply

reply = Reply.find_by_id(1)
topic = reply.topic
topic2 = Topic.find_by_id(1)
p topic.equal? topic2 # 内存比较结果是false

这个可以理解,但是

reply = Reply.find_by_id(1)
topic = Topic.find_by_id(1)
p reply.topic.equal? topic # 内存比较结果是true

看日志,原因是 reply.topic 没有重新查询数据库,但是

现在我只知道现象是这样的,但不清楚 mongoid 的缓存是怎么弄的? 还有什么合适场景,如何正确运用这个特性 大家帮忙稍微讲解一下

开启了 IdentityMap 吧?

#1 楼 @hooopo 麻烦顺便问下这里的 :inverse_of => :replies 是什么含义,看文档说:inverse_of 对象可以在内存中是同一份,但是不太理解 能不能帮新手讲解一下,谢谢

#3 楼 @whatisruby 我没用过 mongoid。。不过这东西应该和 AR 里的类似:

假设 f(x) -> y,那么 f(x) 的反函数是 g(y) inverse_of 的作用是在你第一次运行 f(x) 并得到结果 y 的时候,就把反函数 g(y)-> x 的结果缓存起来了。

@hooopo 咦~~~ 具体作用不是很理解啊 能不能具体以上面 Reply 和 Topic 的例子讲解一下啊(这个应该跟 AR 一样的) 特别是:inverse_of 方向问题, 比如一边加了:inverse_of 后,哪边是 f(x) 能不能 加与不加用代码表示一下区别啊 谢谢啊

#5 楼 @whatisruby 拿最简单的 one-one 来举例子吧: User has_one Account Account belongs_to User 在未设置:inverse_of 的情况下:

u = User.first
[2] pry(main)> account = u.account
  Account Load (0.5ms)  SELECT `accounts`.* FROM `accounts` WHERE `accounts`.`id` = 2 LIMIT 1
[3] pry(main)> account.user
  User Load (0.6ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1

设置了 inverse_of 以后:

class User < ActiveRecord::Base
  has_one :account, :inverse_of => :user
end
[1] pry(main)> u = User.first
  User Load (0.3ms)  SELECT `users`.* FROM `users` LIMIT 1
[2] pry(main)> account = u.account
  Account Load (0.1ms)  SELECT `accounts`.* FROM `accounts` WHERE `accounts`.`user_id` = 3 LIMIT 1
[3] pry(main)> account.user # No SQL Query

其中,把 user.accout 这一方法看成函数就是 account(a_user) -> a_account 对应的反函数是 user(a_account) 一定返回 a_user

#5 楼 @whatisruby 方向问题就得看文档了。。。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号