帮助我了解 mnesia (NoSQL) 建模

Posted

技术标签:

【中文标题】帮助我了解 mnesia (NoSQL) 建模【英文标题】:Help me understand mnesia (NoSQL) modeling 【发布时间】:2011-05-06 00:38:34 【问题描述】:

在了解 Mnesia 的过程中,我仍然在努力思考关系方面的问题。所以我会把我的挣扎放在这里,并寻求解决它们的最佳方法。

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

-record(contact, name, phone). 

现在,我知道我可以将电话定义为始终保存为列表,因此人们可以拥有多个电话号码,我想这就是这样做的方法(是吗?那我该怎么看反过来说,找到一个数字的名字?)

多对多关系 现在让我们假设我有多个可以放入人员的组。组名没有任何意义,它们只是名称;概念是“unix 系统组”或“标签”。天真地,我会将此成员资格建模为 proplist,例如

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

例如,作为上面“联系人”记录中的一个字段。如果我希望能够根据组名快速查找组的所有成员,并且还希望能够查找个人注册的所有组,那么在 mnesia 中对此进行建模的最佳方法是什么?当然,我也可以将其建模为仅包含组标识符的列表。对于与 mnesia 一起使用,最好的建模方法是什么?

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

【问题讨论】:

无需道歉恕我直言,这个问题一点也不愚蠢+1 【参考方案1】:

对于第一个例子,考虑这条记录:

-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

可以有任意数量的“会员”记录。每个用户组都会有一个记录。

【讨论】:

【参考方案2】:

首先,您需要键值存储设计模式。完全没问题。 在我尝试回答您的问题之前,让我们先弄清楚 - 什么是 Mnesia。它是 k-v DB,包含在 OTP 中。因为它是原生的,所以从 Erlang 使用起来非常舒服。但小心点。这是具有非常古老假设的旧数据库(例如线性散列的数据分布)。因此,继续学习和使用它,但对于生产,请花时间浏览 NoSQL 商店以找到最适合您需求的产品。

@telephone 示例。不要将内容存储为字符串 (list()) - 这对于 GC 来说非常繁重。我会创建几个字段,例如 phone_1 :: > 、phone_2 :: >、phone_extra :: [ > ] 并在最常见的查询字段上建立索引。 mnesia indicies 也很棘手 - 当节点崩溃并上升时,它们需要重建自己(这可能需要非常多的时间)。

@family 示例。使用平面命名空间很难。您可以使用更复杂的键。也许为 TheGroup 创建单独的表并保留成员的标识符?或者每个成员都有他所属的组的 ID(难以维护......)。如果你想认识朋友,我会在呈现数据之前实现某种契约(A 是 B 的朋友,如果 B 是 A 的朋友)——这种方法可以处理数据的最终一致性和冲突。

【讨论】:

虽然我没有投票给你,但我似乎很清楚你没有得到我在第二个问题中提出的问题(或者我说得不够清楚)。我想为多对多关系建模; “家人”和“朋友”没有特别指代任何概念。我也已经指出,有成员的列表是一种方式,但要求有更好的方式。 是的,内华达州。但是,您的元组示例似乎是我在第二部分中所写的。第一部分说将多对多建模为保存成员键的单独表。这取决于数据库。在 Riak 中有 2 级键结构 (bucket, key)-(value),因此您可以将所有 goup 成员放在一个桶中。从定义上看,KV 存储并不擅长表示关系。

以上是关于帮助我了解 mnesia (NoSQL) 建模的主要内容,如果未能解决你的问题,请参考以下文章

NOSQL 数据库的建模工具 [关闭]

某些用户的 NoSQL 建模字段可见性

如何监控 mnesia 负载?

Erlang mnesia 数据库访问

Erlang-如何在没有记录的情况下使用 Mnesia

如何在 MongoDB 中建模关系? [复制]