Rails/PostgreSQL:为一个用户存储电话号码列表的最佳方法是什么?

6
我对如何在一列中存储电话号码有些困惑。以下是要求:
  1. 用户可以拥有多个电话号码。
  2. 电话号码必须唯一,因此如果用户A添加了用户B使用的电话号码,则应显示验证错误。
  3. 如果用户有多个电话号码,则应选择默认电话号码。
  4. 解决方案必须与Postgresql兼容。
我想到了四种可能的解决方案:
  1. HStore: 创建一个“phone_number”字段,存储所有电话号码的哈希值。例如:{1=>"+1-800-123-1234", 2=>"9237492734", "default"=>1}。在这种情况下,我需要进行很多查询来确保新的电话号码是唯一的,例如我需要查询 User.where("phone_number @> ('1' => '+1-800-123-1234')") 然后检查2个 User.where("phone_number @> ('2' => '+1-800-123-1234')") ...等等。
  2. 在一个字段中存储电话号码的数组: phone_number将存储逗号分隔的电话号码,例如"+1-800-123-1234,9237492734"。检查现有电话号码将很容易 User.where("phone_number LIKE '%+1-800-123-1234%'") 但是数据库需要很长时间才能处理。还可以像惯例一样将第一个电话号码作为默认电话号码,或添加default_phone字段。
  3. 限制电话号码为3(足以满足需求),并分别创建phone_number_1phone_number_2phone_number_3字段。检查电话号码的唯一性将消耗3个查询。此外还需要添加default_phone
  4. 添加一个新表phone_numbers(id:integer,user_id:integer,phone_number:string,default:boolean),并设置与User模型的has_many关系。虽然没有那么吸引人,但它具有快速查找的优势,并且每个用户都可以拥有无限数量的电话号码。
如有任何想法、提示和建议,将不胜感激。

4
选项4是较为规范的关系型处理方式。您不是为“单个”列创建表,而是对用户和电话号码之间的1:多关系进行建模。我会考虑仅次于它的第二选择是使用数组-但这仅仅是因为Postgres在数组方面具有非常有效和功能丰富的支持。 - user330315
1个回答

9

两个表是解决方案。您可能会有多个用户可以使用相同的电话号码进行联系,例如工作电话或家庭电话,这些电话可能是固定电话。

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  -- other bits of information
);

CREATE TABLE phone_numbers (
  user_id INTEGER REFERENCES users (id),
  phone_number TEXT NOT NULL,
  location TEXT NOT NULL, -- Mobile, home, work
  PRIMARY KEY (user_id, phone_number),
  INDEX (phone_number)
);

如果你真的想强制要求“每个人都有唯一的电话号码,并且该电话号码不能用于联系其他人”,只需向phone_number列添加一个UNIQUE约束即可。

1
如果location列的值应该受到限制(这取决于业务需求),那么最好使用检查约束或外键到一个phone_type表。否则,如果一个用户输入“home”,另一个用户输入“private”,下一个用户输入“personal”作为位置值,将很难找到“home”电话。 - user330315
1
也许甚至可以将其视为域约束。 - wildplasser
1
电话号码的唯一性约束很棘手。1-612-555-1234、612-555-1234等都是同一个号码。最好的方法是选择一个标准格式并在保存之前进行转换。更糟糕的是:(1) 办公室电话有时包括分机号(612-555-1234x201),你可能不能忽略它,(2) 虽然北美电话号码都是一个格式(NANPA),但你可能需要处理"国际"号码。 - David Leppik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接