javascript - 保存Web应用程序的动态图结构

标签 javascript php mysql database web-applications

我一直在寻找这个问题的答案,但还没有找到一个令人满意的解决方案。
我试图为web应用程序存储动态无向图结构。它应该在彼此之间存储用户“订阅”,这可能会经常更改。
传统的数据库解决方案毫无意义。
每个用户的json文件似乎也不是最好的解决方案,原因与数据库解决方案不理想的原因相同。
对我的问题有什么其他的最佳解决方案吗?
提前谢谢!

最佳答案

您所说的结构类型在关系数据库中最有意义(这就是我认为您所说的“传统”的意思)。因为用户之间有订阅,所以这是一种关系,因此,关系数据库最有意义。关系数据库允许不同表之间的显式连接。
对于这种类型的数据,文档数据库(即保存json文档的数据库)是一个非常糟糕的主意。文档数据库在某些方面可以做得很好,但是高度相互依赖的数据(比如某种订阅系统)对文档数据库的使用很差。我们继续下去,我会解释更多的。
你说你的图边是无向的,但是你称它们为“订阅”的事实告诉我它们实际上是有向的:一个用户订阅另一个用户。如果是无方向的,那就更像是在facebook上交朋友或在linkedin上连接:如果我是你的朋友,那么你一定是我的朋友。在订阅系统中(比如google+或twitter),即使我订阅了你,你也不一定需要订阅我。如果我们都订阅了对方,那么它实际上是两个定向的边:一个是我给你的,另一个是你给我的。
因此,最好的解决方案是至少有两个表:主“users”表和辅助“subscriptions”表。“users”表将包含uidnameemail等列。“subscriptions”表只有两列:subscribersubscription。两者都持有“uid”表中的users值,并且表中的每一对值都必须是唯一的。
你问这会不会“膨胀”这么多订阅。首先,你假设你将成为下一个facebook,需要处理数百万或数十亿用户。别担心,至少一开始你不会有那个问题。其次,大多数关系数据库都是logarithmic in their performance用于检索和插入记录,随着用户数量的增加,这些数据库的规模会非常好。对于您期望从文档数据库或磁盘上的json文件获得的行为类型,您的行为要么是linear time complexity,因为您需要遍历数据库中的每个文档,以确保您检查了所有订阅(线性行为比例远低于对数)。或者需要在所有记录中复制订阅服务器/订阅信息。第二种解决方案确实会很臃肿,因为您正在复制大量数据,而且更重要的是,它会冒着很容易失去同步的巨大风险。在这种情况下,失去同步比你想象的要容易得多。
为了向您展示如何做到这一点,我将使用sqlite3 dialect of SQL。这是我的原型,所以我最熟悉它。把它转换成mysql或postgresql应该是相当简单的。下面是创建数据库的语句:

# since `uid` is the primary key, just pass it a
# null value on insertion and the database will 
# generate a unique integer and use that automatically.
# it might also be good to make more than just the uid unique,
# such as their email.
CREATE TABLE users (uid INTEGER PRIMARY KEY,
                    name TEXT,
                    email TEXT);

# we will use the uid for the foreign key reference since this should
# never change, even if the user changes their name or email.
CREATE TABLE subrs (subscriber INTEGER,
                    subscription INTEGER,

                    # make sure each entry of pairs is unique
                    CONSTRAINT uc_edges UNIQUE (subscriber,subscription),

                    # be sure subscribers can only be created for users that exist
                    CONSTRAINT fk_subr FOREIGN KEY (subscriber) REFERENCES users(uid),

                    # be sure subscription can only be created for users that exist
                    CONSTRAINT fk_subee FOREIGN KEY (subscription) REFERENCES users(uid)
                   ); 

这通常有一个很好的附加好处,即在您第一次删除那些订阅之前,您无法删除对它们有订阅的用户。根据您选择的数据库,ymmv,检查您选择的数据库的文档。几乎所有SQL数据库也支持使用外键的行为,而不能用具有尚未存在的外键的值创建记录。使用json文件或文档数据库,很容易留下悬挂订阅或让用户删除需要很长时间,因为您需要修改引用给定用户的每个用户文档。关系型sql数据库可以简化许多在代码中本来可以完成的事情。在应用程序代码中处理此逻辑将为数据处理中的错误和bug带来更多的机会。一点建议:不管你能把什么工作卸载到你的数据库上,你都应该卸载到你的数据库上。专业数据库的测试比代码好得多,并且已经具备了对数据执行许多常见操作的逻辑。
要查找用户的订阅,您可以执行如下查询:
SELECT * FROM subrs WHERE subscriber=some_uid;

要获取给定用户的所有订阅服务器,查询也同样简单:
SELECT * FROM subrs WHERE subscription=some_uid;

要删除用户记录,只需大约三行:
DELETE FROM subrs WHERE subscription=some_uid;
DELETE FROM subrs WHERE subscriber=some_uid;
DELETE FROM users WHERE uid=some_uid;

在文档数据库中,您将有更多的应用程序代码来执行类似的操作,并且您将冒应用程序代码逻辑错误和数据中断的风险。
TL;博士
使用关系型sql数据库。可以在记录之间创建显式关系。因此,使用文档数据库(因为所有关系都是隐含的)来攻击自己并不像使用文档数据库那么容易。像mysql这样的sql数据库也倾向于更好地扩展,包括垂直扩展(即有更多用户记录)和水平扩展(即有更多副本服务器)。

关于javascript - 保存Web应用程序的动态图结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34232364/

相关文章:

javascript - 在弹出窗口上设置 onerror 处理程序

javascript - 如何使用 Javascript 在浏览器的可编辑内容窗口中找出光标处的 DOM 节点?

php - 提供本地json文件: how to cache

MySQL 5 分钟移动平均线(按日期范围对行进行分组)

php - 无法使用 mysql 和 php 向表中添加值

mysql - 如何抓取表中最受欢迎的行?

javascript - toggleClass 缓动仅适用于缓出

javascript - 将 JavaScript 函数转录为 PHP 失败

javascript - JQuery - 使用不同输入的多个过滤器过滤数据属性

php - 在 PHP 中将 RGB 转换为十六进制颜色值