帮助我理解mnesia(NoSQL)建模

12

为了更好地理解Mnesia,我仍然在努力用关系术语来思考。因此,我将在这里列出我的困惑,并询问解决它们的最佳方法。

一对多关系 假设我有一堆人,

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

现在,我知道我可以定义电话号码始终保存为列表,这样人们就可以拥有多个电话号码了,我想这就是正确的做法(是吗?那么如果反过来查找,比如找到一个名字对应的电话号码呢?)

多对多关系 现在假设我有多个可以将人员分组的组。 组名没有任何意义,它们只是名称;概念是“Unix系统组”或“标签”。天真地说,我会将这种成员身份建模为proplist,例如:

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

比如,在上面的“联系人”记录中作为一个字段。如果我想要能够快速查找所有属于某个组的成员,并且还想要能够查找某个个体注册在哪些组中,那么最好的方法是在mnesia中对其进行建模?当然,我也可以将其建模为仅包含组标识符的列表。对于mnesia,最佳建模方式是什么?

如果我的问题很愚蠢,我感到很抱歉。尽管有很多有关mnesia的文档,但整体使用的一些好例子却不足(在我看来)。


1
不需要道歉,在我看来这个问题一点也不愚蠢,给你点赞。 - Peer Stritzinger
2个回答

3

首先,考虑以下记录:

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

contact是一条记录,包含两个字段:namephone,其中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
首先,您要求键值存储设计模式。非常好。 在我回答您的问题之前,让我们搞清楚一件事 - 什么是Mnesia。它是一个k-v数据库,包含在OTP中。因为它是本地的,所以从Erlang中使用非常方便。但要小心。这是一个非常古老的数据库,有着非常古老的假设(例如使用线性哈希进行数据分布)。所以,请继续学习和尝试,但对于生产环境,请花时间浏览NoSQL商店,找到最适合您需求的。
关于电话号码的例子,请勿将其存储为字符串(list())- 这对GC来说非常沉重。我会创建几个字段,如phone_1 :: < < binary > > ,phone_2 :: < < binary > > ,phone_extra :: [ < < binary > > ],并在最频繁的查询字段上建立索引。此外,mnesia索引很棘手 - 当节点崩溃并重新启动时,它们需要重新构建自己(这可能需要非常长的时间)。

@family 示例。在扁平化命名空间下相当困难。你可以尝试使用更复杂的键值..也许为TheGroup创建一个单独的表,并保留成员的标识符?或者每个成员都有他所属的组的ID(很难维护..)。如果你想要识别朋友,我会在呈现数据之前实现某种形式的合同(A是B的朋友,当且仅当B是A的朋友)- 这种方法可以处理数据的一致性和冲突问题。


虽然我没有给你投反对票,但我觉得你没有理解我在第二个问题中的意思(或者我没有表达清楚)。我想建立多对多关系;“家庭”和“朋友”并不特指任何概念。我已经指出列表是一种方法,但我希望找到更好的方法。 - CONTRACT SAYS I'M RIGHT
是的,nev。但是你的元组示例似乎是我在第二部分中编写的内容。第一部分说将多对多建模为保存成员键的单独表格。这取决于数据库。在Riak中,有2级键结构(bucket,key)-(value),因此您可以在一个bucket中拥有所有群组成员。从定义KV存储不擅长表示关系。 - user425720

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