我正在实现跟踪用户阅读过哪些文章的功能。
create_table "article", :force => true do |t|
t.string "title"
t.text "content"
end
到目前为止,这是我的迁移:
create_table :user_views do |t|
t.integer :user_id
t.integer :article_id
end
将始终查询user_views表以查找两列,而不仅仅查找一列。我的问题是我的索引应该是什么样子。这些表的顺序是否存在差异,是否应该有更多选项或其他。我的目标数据库是Postgres。
add_index(:user_views, [:article_id, :user_id])
感谢。
更新:
因为在两列中只能存在一行包含相同值的行(因为在知道user_id是否读取了article_id时),我应该考虑:unique选项吗?如果我没有弄错,那意味着我不必自己进行任何检查,只需在用户每次访问文章时插入一次。
答案 0 :(得分:183)
订单在索引方面很重要。
[:user_id, :article_id]
上编入索引,则可以在user_id
或user_id AND article_id
上执行快速查询,但不能在article_id
上执行快速查询。您的迁移add_index
行应如下所示:
add_index :user_views, [:user_id, :article_id]
在Rails中执行此操作的一种简单方法是在模型中使用validates
,其范围为uniqueness
,如下所示(documentation):
validates :user, uniqueness: { scope: :article }
答案 1 :(得分:20)
关于检查验证时与索引的唯一性的警告:后者由数据库完成,而引物由模型完成。由于可能同时运行模型的多个并发实例,因此验证受竞争条件的影响,这意味着在某些情况下它可能无法检测到重复(例如,在同一时间提交两次相同的表单)。