帮助我理解mnesia(NoSQL)建模

问题描述:

在我对Mnesia的理解中,我仍然在用关系术语思考。所以我会把我的努力放在这里,并寻求解决它们的最好方法。帮助我理解mnesia(NoSQL)建模

一个一对多-关系 说我有一堆人,

-record(contact, {name, phone}). 

现在,我知道我可以定义手机始终保存为一个列表,让人们可以有多个电话号码,我想这就是这样做的方式(是吗?然后我怎么看这个反过来说,找到一个数字的名字?)。 。

多到多对多关系 现在让我们假设我有多个组,我可以把人组名没有任何意义,他们只是名称;该概念是“unix系统组”或“标签”。天真,我将这个成员作为一个字段的“接触”的记录中从上面,建模为proplist这样,像

{groups [{friends, bool()}, {family, bool()}, {work, bool()}]} %% and so on... 

例如。如果我希望能够快速查找基于组名的所有成员,并希望能够查找个人注册的所有组,那么在mnesia中建模的最佳方法是什么?当然,我也可以将其作为仅包含组标识符的列表进行建模。用于mnesia,建模的最佳方式是什么?

我很抱歉,如果这个问题是愚蠢的。有很多关于mnesia的文档,但它缺乏(IMO)整体使用的一些很好的例子。

+1

没有必要道歉恕我直言,这个问题并非愚蠢的所有+1那 – 2010-11-06 17:02:13

对于第一个例子,考虑这样记载:

-record(contact, {name, [phonenumber, phonenumber, ...]}). 

contact是两个领域,namephone其中手机的电话号码列表中的记录。正如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 

可以有任意数量的“成员资格”记录。每个用户组将有一条记录。

+0

我会接受这个答案。谢谢。 – 2010-12-21 16:31:08

首先,您要求提供键值存储设计模式。非常好。 在我尝试回答你的问题之前,让我们先说清楚 - Mnesia是什么。它是k-v DB,包含在OTP中。因为它是本地的,所以从Erlang使用起来非常舒服。不过要小心。这是具有非常古老假设的旧数据库(例如具有线性散列的数据分布)。因此,请继续学习并使用它,但是对于生产来说,花点时间并浏览NoSQL商店即可找到满足您需求的最佳选择。

@telephone示例。不要将东西存储为字符串(list()) - 对于GC非常重要。我会将诸如phone_1 :: < < <二进制>>,phone_2 :: < < < < <二进制>>,phone_extra :: [< <二进制>>]并在最频繁的查询字段上构建索引。此外,mnesia的痕迹很棘手 - 当节点崩溃并且上升时,他们需要重建自己(可能需要很长时间)。

@family示例。平面命名空间非常困难。你可以玩更复杂的键。也许为TheGroup创建单独的表并保留成员的标识符?或者每个成员都拥有他所属团体的ID(难以维护..)。如果你想认识朋友,我会在呈现数据之前执行某种契约(A是B的朋友,如果B是A的朋友) - 这种方法将应对数据中的最终一致性和冲突。

+0

嘿,也许有人评论之前,这downvote? – user425720 2010-11-07 15:36:42

+0

虽然我没有投票给你,但在我看来很清楚你没有得到我在第二个问题中提出的问题(或者我没有说清楚)。我想模拟多对多的关系; “家人”和“朋友”并没有特别提到任何概念。我也已经指出,与会员名单是一种方式,但要求更好的方式。 – 2010-11-07 17:01:44

+0

是啊,内夫。然而,你的元组示例似乎是我在第二部分写的。第一部分说要将多对多模型作为单独的表格来存放成员的键。这取决于数据库。在Riak中有两级关键结构(存储桶,关键) - (值),因此您可以在一个存储桶中拥有所有关联成员。从定义来看,KV商店并不擅长表示关系。 – user425720 2010-11-07 17:49:59