问一下,自己一个业余的小项目,希望实现用户对项目属性的自定义,可以新增字段或者修改、删除字段,请问如何设计数据库比较好? 采用 MongoDB 或者利用 PostgreSQL 的 JSONB 数据类型来实现是否会简单些? 主要考虑实现的简洁和使用的简单。
本人用的是最土的方案,没用 MongoDB,没用 JSONB,用冗余字段。
# 表名:客户资料表
# 描述:t1, s1等这些列的定义见columns表。
class CreateCustomers < ActiveRecord::Migration
def change
create_table :customers do |t|
t.belongs_to :company, index: true
t.belongs_to :salesman
t.integer :t1
t.integer :t2
t.integer :t3
t.integer :t4
t.integer :t5
t.integer :t6
t.string :s1 #这是手机号,如果存在效率问题,可以考虑用bigint
t.string :s2
t.string :s3
t.string :s4
t.string :s5
t.date :d1
t.date :d2
t.date :d3
t.datetime :dt1
t.datetime :dt2
t.integer :t7
t.integer :t8
t.integer :t9
t.string :s6
t.string :s7
t.string :s8
t.string :s9
t.string :s10
t.string :s11
t.string :s12
t.string :s13
t.string :s14
t.string :s15
t.string :s16
t.string :s17
t.string :s18
t.string :s19
t.string :s20
t.timestamps
end
end
end
# 表名:自定义数据列
class CreateColumns < ActiveRecord::Migration
def change
create_table :columns do |t|
t.belongs_to :company, index: true
t.string :name # 值是s3, t1, d2, dt2这样的数据。's'起头表示输入型, 't'起头表示下拉选框型(下拉选项值需要关联options表), 'd'起头表示日期型,'dt'起头表示时间型;N表示第几个
t.string :title
t.integer :width
t.timestamps
end
end
end
# Column中类型为“下拉选项”的具体选项
class CreateOptions < ActiveRecord::Migration
def change
create_table :options do |t|
t.belongs_to :company, index: true
t.integer :tid #Column表的t开头的字段id,如't2',则此处值为2
t.integer :value
t.string :text
end
end
end
@chenge 那样的做好感觉不简洁啊。表里面要存项目 ID,属性 ID,属性值,如果一个项目 10 个属性,10000 个项目就有 100000 个属性值。。。。。
典型的属性组设计嘛,可以看看 spree 的,没有 model annotate,自己翻 migration 吧:
@chenge @hooopo @rubyist518 @gazeldx 我目前的想法是用 JSONB 字段来存每个项目的属性和值,在加个表管理每个项目的属性。不知道可行否?征求一下大家意见。
关系型数据库的解决方案叫Entity–attribute–value model (EAV) 主要有三个表:
后来用上 PostgreSQL 的 jsonb 格式,jsonb 能够加 gin 索引,空间和查询性能都完胜。对上面的 EVA 作一点优化,变成两个表
MongoDB 没考虑,我的经验是大部分的数据都是 schema 的。schemaless 在 dev 时很爽,但上线后迭代也是要做 migrations