在 Rails 中更高效地查找或创建多个记录
我有一个应用程序需要发送用户活动邀请。当用户邀请朋友(用户)参加活动时,如果尚不存在一条将用户连接到该活动的新记录,则会创建一条新记录。我的模型由用户、事件和 events_user 组成。
class Event
def invite(user_id, *args)
user_id.each do |u|
e = EventsUser.find_or_create_by_event_id_and_user_id(self.id, u)
e.save!
end
end
end
用法
Event.first.invite([1,2,3])
我认为上述方法不是完成我的任务的最有效方法。我设想了一种类似的方法
Model.find_or_create_all_by_event_id_and_user_id
,但不存在。
未经验证的模型
class User
has_many :events_users
has_many :events
end
class EventsUser
belongs_to :events
belongs_to :users
end
class Event
has_many :events_users
has_many :users, :through => :events_users
end
I have an app that needs to send out user invitations for events. When a user invites a friend (user) to an event, a new record connecting the user to the event is created if one doesn't already exist. My models consists of user, event, and events_user.
class Event
def invite(user_id, *args)
user_id.each do |u|
e = EventsUser.find_or_create_by_event_id_and_user_id(self.id, u)
e.save!
end
end
end
Usage
Event.first.invite([1,2,3])
I don't think the above is the most efficient way to accomplish my task. I envisioned a method like
Model.find_or_create_all_by_event_id_and_user_id
but one does not exist.
Models without validations
class User
has_many :events_users
has_many :events
end
class EventsUser
belongs_to :events
belongs_to :users
end
class Event
has_many :events_users
has_many :users, :through => :events_users
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先获取所有现有记录,然后创建所有缺失的记录可能会更快:
这样,如果所有
event_users
均已存在,您只需进行 1 次查询。但是,如果不存在event_users
,则与每个EventUser
创建所需的查询数量相比,此方法会执行额外的查询。It might be quicker to first fetch all existing records and then create all missing records:
This way you make only 1 query if all
event_users
already exist. However, if noevent_users
exist, this method does an extra query - compared to the number of queries required for each singleEventUser
creation.你所说的最有效率是什么意思?我假设高效意味着高性能,而不是优雅、干燥、可维护的代码等。
从数据库的角度来看,如果您想将 100 条记录插入数据库,这将转换为 100“INSERT INTO events_models VALUES (x, x)" sql 查询(如果您还有唯一性验证,则可能有 100 个“SELECT COUNT(*) ..”查询)。因此,即使您想要的方法在 AR 中实现,它仍然会在属性数组上有一个循环,并保存每个 event_id、user_id 对。
从 Ruby/Rails 的角度来看,如果你想在模型上进行验证/回调等,那么你必须在循环中一一创建一个 ActiveRecord 实例。现在,如果您想超级优化您的方法(删除 ActiveRecord 类的实例化),您可以手动编写 sql 查询(从而节省一些时间和内存)。然而,与风险相比,收益微乎其微。
顺便提一句,
e.save!
不是必需的,因为:What do you mean by most efficient? I will assume that by efficient you mean performant, and not elegant, DRY, maintainable code, etc.
From a DB viewpoint, if you want to insert 100 records into the DB, this will translate to 100 "INSERT INTO events_models VALUES (x, x)" sql queries (and maybe 100 "SELECT COUNT(*) .." queries if you also have a uniqueness validation). So, even if the method you want would be implemented in AR, it would still have a loop on the attribute arrays with a save on each event_id, user_id pair).
From Ruby/Rails point of view, if you want to have validations/callbacks/etc on your model, then you must create an ActiveRecord instance one by one in a loop. Now, if you want to super optimize your method (to drop the instantiation of an ActiveRecord class), you can manually write the sql queries (therefore saving some time and memory). The gains are however minimal in comparison with the risks.
Btw,
e.save!
is not necessary as:如果连接模型中没有任何验证或回调,最快的方法是原始 sql:
在进行上述调用之前,您可以编写一个查询来消除 user_ids 中的现有记录。我有一个关于此的上一个问题< /a>,特别是关于没有模型的连接表。
由于您确实有一个连接模型,因此您可以使用 ar-import gem:
If you don't have any validations or callbacks in the join model, the fastest method is raw sql:
You could write a query to eliminate existing records from user_ids before making the above call. I had a previous question about this, specifically about join tables that don't have a model.
Since you do have a join model, you could use the ar-import gem: