旧创建的联接表如何在没有索引的情况下工作?

时间:2019-01-09 07:03:57

标签: ruby-on-rails ruby

我以前通过迁移创建了一个联接表:

class CreateJoinTableCategoryListing < ActiveRecord::Migration[5.2]
  def change
    create_join_table :categories, :listings do |t|
      # t.index [:category_id, :listing_id]
      # t.index [:listing_id, :category_id]
    end
  end
end

我正在回想一下,因为我将要创建一个新的联接表。但是当我看着它的时候,我注意到我迁移时仍然注释掉了t.index,并且联接的表仍然可以正常运行。

我读到了这篇文章,却没有发现有人做相同或不需要的帖子。

如何处理那些从未迁移过的索引?它们有何需求?

我正在创建新迁移:

class CreateJoinTable < ActiveRecord::Migration[5.2]
  def change
    create_join_table :users, :affiliates do |t|
      # t.index [:user_id, :affiliate_id]
      # t.index [:affiliate_id, :user_id]
    end
  end
end

我应该在这里选择哪个索引?

其工作方式是,会员可以手动向表提交“佣金”(确实需要将其添加到迁移中),但是如果佣金已更新,则应代替该列而不创建新行。

用户将与此无关,并且大部分将由联属会员更新以更新他们对该用户的佣金率。

更新:

是否甚至可以在联接表中添加另一个字段?

我想在表中添加:commission,但我找不到任何文档可以为此做任何事情。我应该只在users表中定义佣金率并取消join表吗?

更新2:

最终刮掉了这个想法,并保留了我目前仅通过用户和会员联盟进行操作的方法。我取消了UsersAffiliates的想法,因为这种情况不需要它。

1 个答案:

答案 0 :(得分:0)

  

如何处理那些永不迁移的索引以及如何需要   是吗?

Rails中的所有类型的关联都可以在没有索引的情况下工作。唯一需要做的就是存在正确的表和列。

但是,随着数据库规模的增长,索引对于性能至关重要。它们还提供诸如唯一性之类的约束,以确保duplicate data cannot be inserted due to race conditions

  

我应该在这里选择哪个索引?

Rails生成两个不同索引的全部原因是,您应该选择与您最常搜索表的方式相对应的索引。如果您最常使用User.joins(:affilitates),则可以选择t.index [:user_id, :affiliate_id]

  

应该如何工作,是会员可以手动提交   表的“佣金”(确实需要添加到   迁移)。

create_join_table宏创建一个以has_and_belongs_to_many关联命名的联接表。

has_and_belongs_to_many关联的主要问题是它们没有头。没有模型,因此无法直接查询表或添加其他元数据列。

您想要的是一个has_many :through关联。

class User < ApplicationRecord
  has_many :user_affiliates
  has_many :affiliates, through: :user_affiliates
end

class Affiliate < ApplicationRecord
  has_many :user_affiliates
  has_many :affiliates, through: :user_affiliates
end

# call this whatever you want
class UserAffiliate  < ApplicationRecord
  belongs_to :user
  belongs_to :affilitate
end

虽然has_and_belongs_to_many使用表命名方案users_affilitiesplural_plural),但您想将user_affilities用于has_many through:关联。

您可以通过以下方式解决此问题:

  1. 只需通过常规生成器rail g model user_affiliate生成表/模型即可。
  2. 如果表存在write a migration to rename the table
  

但如果佣金已更新,则应代替   列,而不创建新行。

您可以通过以下方法解决此问题:

  1. t.index [:user_id, :affiliate_id], unique: true两列上添加唯一的复合索引。
  2. 在联接模型中添加唯一性验证。 validates_uniqueness_of :user_id, scope: :affiliate_id
  3. 在控制器中使用.find_or_initialize_by更新现有行(如果存在),而不是创建新行(如果已经存在)。