我有一个Ruby on Rails应用程序,这是一种游戏。有一个用户模型,每个用户有大约10个属性,每个属性有大约10个可能的值。用户使用通过或失败布尔值对其他用户进行评级。我希望每次用户被评为通过时跟踪统计数据。因此,为每个用户提供他们所传递的属性的标签,以及将他们评为通行证的属性。我想要一个统计页面,用户可以看到10个属性中的每一个,以及每个属性值的计数,包括他们通过的人员以及通过他们的人员。
我提出的是一个名为Stat的模型,其中包含与用户的belongs_to / has_one关联。
# app/models/user.rb
has_one :stat
# app/models/stat.rb
belongs_to :user
统计信息表为每个用户和user_id字段都有一行。然后,对于用户的评价者和用户评价者(100 x 2)时,每个用户的10个属性(因此100个字段)的10个可能选项中的每一个都有整数字段。这总共有201个领域,看起来非常多。当用户通过另一个用户时,对于每个传递的用户的属性值,将1添加到评估者行的统计表中,并为每个评估者的属性值添加1到ratee的行。
每个用户都有一个统计信息页面,显示他们通过的10个属性中的每个属性的10个可能值中的每个值,并分别为谁传递它们。
我的问题是,一个包含201个字段的大型统计表是设置它的最佳方式。我试着把它分成两个表,一个用于rater,一个用于ratee,但设置似乎只是增加了更多的复杂性。有没有更好的方法,我没有看到这样做?
答案 0 :(得分:0)
你的直觉是正确的。想象一下,如果你添加了一个新的属性来跟踪,你必须做的工作?您必须编写另一个迁移。
我建议使用连接表来跟踪正在评估的用户,作为评估者的用户,stat_id和分数。这还需要统计表。
class Stat < ActiveRecord::Base
validates_presence_of :name
end
class UserStatRating < ActiveRecord::Base
belongs_to :user
belongs_to :evaluator, class_name: 'User'
belongs_to :stat
validates_presence_of :score
end
class User < ActiveRecord::Base
has_many :user_stat_ratings, dependent: :destroy
end
使用此方法,您可以在路上Stat.create(name: 'new stat')
创建更多统计信息,而无需更改架构。
答案 1 :(得分:0)
拥有200多列的表几乎是最容易想到的解决方案。
&#34;经典&#34;这样做的方法是创建一个键/值表:
class CreateStats < ActiveRecord::Migration[5.0]
def change
create_table :attributes do |t|
t.string :key
end
add_index :attributes, :key
end
end
class CreateUserStats < ActiveRecord::Migration[5.0]
def change
create_table :user_stats do |t|
t.belongs_to :user, foreign_key: true
t.belongs_to :attribute, foreign_key: true
t.boolean :value
t.timestamps
end
add_index :stats, [:key_id, :user_id]
end
end
class Stat < ApplicationRecord
has_many :user_attributes
end
class UserStat < ApplicationRecord
belongs_to :user
belongs_to :stat
delegate :key, to: :stat
end
另一种变体是您可以在主表中存储可用键以提供数据规范化:
class UserStat < ApplicationRecord
belongs_to :user
belongs_to :stat
has_many :stat_reviews
delegate :key, to: :stat
end
class StatReview < ApplicationRecord
belongs_to :user_stat
belongs_to :reviewer, class_name: :user
end
(+)它是一个常规的关系表,因此您可以使用ActiveRecord关联将UserAttributes链接到某种评级。
{{1}}
( - )一个列在关系数据库中只能有一个类型。这通常意味着您必须使用字符串列并在应用程序中键入强制转换值。
Postgres现在有其他数据类型,如HSTORE,JSON和JSONB,可用于存储任意键/值类型数据结构。
(+)无类型/无模式,因此您可以使用您想要的任何类型的值。
( - )非关系,所以你不能使用关联。