ruby-on-rails Rails脚本,用于查找两列与任何其他记录匹配的记录

qlfbtfca  于 2023-05-19  发布在  Ruby
关注(0)|答案(2)|浏览(160)

我正在尝试查找inviter_id和invitee_id与任何其他邀请匹配的所有邀请。
但是为了概括这个问题,如果我从查找其first_name和last_name与任何其他用户匹配的用户的Angular 来讨论这个问题,可能会更好。
这个脚本在我的开发环境中运行良好,但在生产环境中却不行,因为记录太多了。

matches = []

User.all.each_with_index do |user1, index|
    start = index + 1
    User.all[start..-1].each do |user2|
        if ((user1.first_name == user2.first_name) && (user1.last_name == user2.last_name)
            matches << user2
        end
    end
end

有更好的方法来实现这一点吗?

jckbn6z7

jckbn6z71#

这种搜索永远不会大规模地执行。如果这是您业务逻辑中经常需要的内容,我建议在创建/销毁/更新用户时将对重复用户的引用缓存在users表中。
如果只是偶尔运行的脚本,则可能会有一些性能改进:

matches = []

User.all.each do |user|
  duplicates = User.where(first_name: user.first_name, last_name: user.last_name).where.not(id: user.id)
  (matches += duplicates.to_a) unless duplicates.empty?
end

编辑:天啊,我刚刚发现了一个快速的方法来做到这一点!

User.all.
     group_by{|u| u.first_name+u.last_name}.
     values.
     select{|users| users.length > 1}

和前面一样,通过只选择您感兴趣的字段进行优化。

1cosmwyk

1cosmwyk2#

这是留给数据库的更好的东西,因为随着更多的“用户”被添加,迭代所有的“用户”将变得越来越低效。
由于您的描述是 “inviter_id和invitee_id匹配任何其他邀请的邀请”,因此我将专注于此,而不是混淆用户。
您可以使用以下查询获取此信息:Example

SELECT 
invitations.* 
FROM 
invitations
WHERE 
    (invitations.inviter_id,invitations.invitee_id) IN (
      SELECT 
        invitations.inviter_id,
        invitations.invitee_id
      FROM 
        invitations
      GROUP BY 
        invitations.inviter_id,
        invitations.invitee_id
      HAVING 
        COUNT(*) > 1 
      )

我们可以用更 * Rails * 的方式重写如下:

invites_tbl = Invitation.arel_table
duplicate_invites = Invitation.where(
  Arel::Nodes::Grouping.new([invites_tbl[:inviter_id],invites_tbl[:invitee_id]]).in(
    Invitation
      .select(:inviter_id,:invitee_id)
      .group(:inviter_id,:invitee_id)
      .having(Arel.star.count.gt(1))
      .arel
  )
)

这将返回所有Invitiation对象,其中存在具有相同inviter_idinvitee_id的其他Invitation。
然后,您可以根据需要对其进行进一步分组,例如:

duplicate_invites.group_by {|i| [i.inviter_id, i.invitee_id]}

相关问题