在我理解Mnesia的过程中,我仍然在用关系术语思考。因此,我将把我的斗争放在这里,并寻求解决它们的最佳方法。
一个一对多-关系 说我有一群人,
-record(contact, {name, phone}).
现在,我知道我可以将手机定义为始终保存为列表,因此人们可以拥有多个电话号码,我想这就是这样做的方法(是吗?我怎么会看到这个反过来说,找一个数字的名字?)。
许多一对多-关系 现在让我们假设我有多个团体可以让人们进去。团体名称没有任何意义,它们只是名字;概念是“unix系统组”或“标签”。天真的,我会把这个会员资格建模为一个名单,比如
{groups [{friends, bool()}, {family, bool()}, {work, bool()}]} %% and so on...
例如,作为上面“联系”记录中的字段。如果我希望能够快速查找基于组名的组中的所有成员,并且还希望能够查找个人注册的所有组,那么在mnesia中对此进行建模的最佳方法是什么?当然,我也可以将其建模为仅包含组标识符的列表。要与mnesia一起使用,对此进行建模的最佳方式是什么?
如果这个问题愚蠢,我道歉。关于mnesia的文档很多,但它缺乏(IMO)一些很好的整体使用示例。
答案 0 :(得分:3)
对于第一个示例,请考虑以下记录:
-record(contact, {name, [phonenumber, phonenumber, ...]}).
contact
是包含两个字段name
和phone
的记录,其中phone是一个电话号码列表。正如user425720所说,将这些存储为除字符串以外的其他东西是有意义的,例如,如果您对小存储空间有极高的要求,那么。
现在这里出现了难以“获取”键值存储的部分:您还需要存储反向关系。换句话说,您需要类似以下的内容:
-record(phone, {phonenumber, contactname}).
如果您的应用程序中有一个图层来抽象数据库处理,您可以在添加/更改联系人时始终添加/更改电话记录。
-
对于第二个示例,请考虑以下两个记录:
-record(contact, {uuid, name, [group_id, group_id]}).
-record(group, {uuid, name, [contact_id, contact_id]}).
最简单的方法是只存储指向相关记录的ID。由于Mnesia没有参照完整性的概念,如果你删除一个组而不从所有用户中删除该组,这可能会变得不同步。
如果您需要在联系人记录中存储组的类型,您可以使用以下内容:
-record(contact, {name, [{family, [group_id, group_id]}, {work, [..]}]}).
-
您的第二个问题也可以通过使用中间记录来解决,您可以将其视为“成员资格”。
-record(contact, {uuid, name, ...}).
-record(group, {uuid, name, ...}).
-record(membership, {contact_uuid, group_uuid}). # must use 'bag' table type
可以有任意数量的“会员”记录。每个用户组都会有一条记录。
答案 1 :(得分:-1)
首先,您要求提供键值存储设计模式。非常好。 在我尝试回答你的问题之前,我们先说清楚 - 什么是Mnesia。它是k-v DB,包含在OTP中。因为它是原生的,所以从Erlang使用起来非常舒服。不过要小心。这是具有非常古老假设的旧数据库(例如,具有线性散列的数据分布)。所以继续,学习和玩它,但是为了生产,请花时间浏览NoSQL商店以找到最符合您需求的商品。
@telephone示例。不要将东西存储为字符串(list()) - 对于GC来说它非常重。我会做几个字段,如phone_1 ::< <二元> > ,phone_2 ::< <二元> >,phone_extra :: [< <二元> > ]并在最常见的查询字段上构建索引。 mnesia指标也很棘手 - 当节点崩溃并上升时,它们需要自己重建(它可能需要很长时间)。
@family示例。平面命名空间很难。您可以使用更复杂的密钥..也许为TheGroup创建单独的表并保留成员的标识符?或者每个成员都会拥有他所属的团体(很难维护......)。如果你想认识朋友,我会在呈现数据之前实现某种合同(A是B的朋友,如果B是A的朋友) - 这种方法可以应对最终的一致性和数据冲突。