ChatGPT解决这个技术问题 Extra ChatGPT

你如何在 NoSQL 中跟踪记录关系?

我试图找出 NoSQL KVP 或文档数据库中的外键和索引的等价物。由于没有关键表(添加标记两个对象之间关系的键),我真的很难理解如何以对普通网页有用的方式检索数据。

假设我有一个用户,这个用户在整个网站上留下了很多评论。我能想到的跟踪用户评论的唯一方法是

将它们嵌入到用户对象中(这似乎没什么用) 创建并维护一个 user_id:comments 值,其中包含每个评论的键 [comment:34, comment:197, etc...] 的列表,以便我可以将它们作为需要。

但是,以第二个示例为例,当您使用它来跟踪其他内容时,您很快就会碰壁积极评论。它也很容易出现竞争条件,因为许多页面可能会同时尝试更新它。

如何在 NoSQL 数据库中跟踪如下关系?

用户的所有评论

所有活跃评论

所有带有[关键字]标签的帖子

俱乐部中的所有学生 - 或学生所在的所有俱乐部

还是我想错了?

在 NoSQL 数据库中没有一种方法可以做到这一点,这个问题类似于询问我将如何跟踪 C 程序中的关系。
哇,那么我想关于 NoSQL 取代 RDBMS 的炒作是不可能的。
是的,NoSQL 肯定被夸大了。我并不是说新技术在适当的情况下没有用,但认为它们将取代 RDBMS 是荒谬的。请参阅en.wikipedia.org/wiki/Hype_cycle
难道你不会只有“用户”的集合和评论的集合。然后,每个评论都只是作为“作者”属性,其值是对用户 ID 的引用?

B
Bill Karwin

关于如何以“NoSQL 方式”存储多对多关联的所有答案都归结为同一件事:冗余存储数据。

在 NoSQL 中,您不会根据数据实体之间的关系来设计数据库。您根据将针对它运行的查询来设计数据库。使用与非规范化关系数据库相同的标准:如果数据具有凝聚力更重要(考虑以逗号分隔的列表而不是规范化表中的值),那么就这样做。

但这不可避免地会以牺牲其他类型的查询(给定用户对任何文章的评论)为代价来优化一种类型的查询(例如,任何用户对给定文章的评论)。如果您的应用程序需要对两种类型的查询进行同等优化,则不应进行非规范化。同样,如果您需要以关系方式使用数据,则不应使用 NoSQL 解决方案。

非规范化和冗余存在冗余数据集彼此不同步的风险。这称为异常。当您使用规范化的关系数据库时,RDBMS 可以防止异常。在非规范化数据库或 NoSQL 中,编写应用程序代码以防止异常成为您的责任。

有人可能认为 NoSQL 数据库为您完成防止异常的艰苦工作会很棒。有一种范式可以做到这一点——关系范式。


“如果您需要以关系方式使用数据,则不应使用 NoSQL 解决方案” - 那么其他运行 NoSQL 的人如何摆脱它呢?当您第一次设计应用程序时,您怎么可能知道查询数据的所有方式? Fox 示例,我可能想要最近的评论、用户评论、标签评论、给定帖子的评论、标记为垃圾邮件的评论、活跃评论、评分最高的评论等。
确实——没有像 NoSQL 的拥护者喜欢声称的那样“它只是工作”这样的事情。要么为关系数据建模预先进行大量分析,要么为最优先的查询预先进行大量分析,或者在发现设计的哪些部分时在整个项目中进行大量昂贵的重构事先没有得到足够的分析。
如果我们冗余存储数据,我们应该如何更新?例如,更改了他的名字,并写了一些评论。他的名字已经在用户集合中被更改了,但是如何更改评论集合中所有冗余存储的名字?
@M98,啊,你发现了这个策略的弱点。您必须了解所有需要更新的地方,然后在您的应用程序中编写代码以在更新任何地方时更新所有这些地方。祝你好运!
非规范化的关系数据库也存在同样的问题。
B
Basit Anwer

couchDB 方法建议在 map 阶段发出适当的东西类,并在 reduce 中对其进行总结。因此,您可以映射所有评论并为给定用户发出 1,然后仅打印出来。然而,它需要大量的磁盘存储来构建 couchDB 中所有可跟踪数据的持久视图。顺便说一句,他们也有这个关于关系的 wiki 页面:http://wiki.apache.org/couchdb/EntityRelationship

另一方面,Riak 拥有建立关系的工具。它是链接。您可以将链接(此处为注释)文档的地址输入到“根”文档(此处为用户文档)。它有一个技巧。如果它是分发的,它可能会一次在多个位置进行修改。它会导致冲突,结果是巨大的矢量时钟树:/ ..不是那么糟糕,不是那么好。

Riak 还有另一个“机制”。它有 2 层键名空间,即桶和键。因此,以学生为例,如果我们有俱乐部 A、B 和 C 以及学生 StudentX、StudentY,您可以保持以下约定:

{ Key = {ClubA, StudentX}, Value = true }, 
{ Key = {ClubB, StudentX}, Value = true }, 
{ Key = {ClubA, StudentY}, Value = true }

并读取关系只需列出给定存储桶中的键。那有什么问题?这该死的慢。列出存储桶从来都不是 riak 的优先事项。它越来越好。顺便提一句。您不会浪费内存,因为此示例 {true} 可以链接到 StudentX 或 Y 的单个完整配置文件(此处不可能发生冲突)。

如您所见,NoSQL!= NoSQL。您需要查看具体的实现并自己进行测试。

之前提到的列存储看起来很适合关系..但这完全取决于您的 A 和 C 以及 P 的需求;)如果您不需要 A 并且您的字节数少于 Peta 就离开它,继续使用 MySql 或 Postgres。

祝你好运


Riak 最近发布了 v1.0,在使用 LevelDB 后端时增加了对二级索引的支持。非常有价值的功能。
T
Tom Clarkson

user:userid:comments 是一种合理的方法 - 将其视为 SQL 中的列索引的等价物,并附加要求您不能对未索引的列进行查询。这是您需要考虑您的要求的地方。包含 3000 万个项目的列表并非不合理,因为它很慢,而是因为用它做任何事情都不切实际。如果您的真正要求是显示一些最近的评论,那么您最好保留一个非常短的列表,以便在添加评论时更新 - 请记住,NoSQL 没有规范化要求。竞争条件是基本键值存储中列表的问题,但通常要么您的平台正确支持列表,您可以使用锁做一些事情,或者您实际上并不关心失败的更新。与用户评论相同 - 创建索引关键字:posts 更多相同 - 可能是作为学生属性的俱乐部列表和该字段上的索引以获取俱乐部的所有成员


那么,基本上一切都只需要列表吗?似乎应该有一种比手动跟踪 id 字符串更复杂的方法。一方面,在它们变得有用之前,你只能走这么远。再说一次,NoSQL 技术的主要子项目(MongoDB、CouchDB、Membase 等)都是新项目,所以也许我只需要给他们更多时间来想出更好的方法来跟踪关系。
如果您使用的是 NoSQL(AKA 非关系数据存储),则需要停止以关系术语思考。使用的方法在平台之间会有所不同,但是您必须管理索引的基本思想是相当普遍的。您给出的关系示例在 NoSQL 中以两种不同的方式建模:1)存储 - 与 SQL 不同,列可以具有多个/复杂的值,因此子对象只是父对象的一部分。 2) 搜索 - 您的长列表实际上是对可搜索性的要求,这意味着索引 - 您可以使用简单的自定义列表或更完整的搜索引擎。
B
Basit Anwer

你有

"user": {
    "userid": "unique value",
    "category": "student",
    "metainfo": "yada yada yada",
    "clubs": ["archery", "kendo"]
}

"comments": {
    "commentid": "unique value",
    "pageid": "unique value",
    "post-time": "ISO Date",
    "userid": "OP id -> THIS IS IMPORTANT"
}

"page": {
    "pageid": "unique value",
    "post-time": "ISO Date",
    "op-id": "user id",
    "tag": ["abc", "zxcv", "qwer"]
}

那么在关系数据库中,正常的做法是在一对多关系中对数据进行规范化。这与您在 NoSQL 数据库中所做的相同。只需索引您将用来获取信息的字段。

例如,对您来说重要的索引是

评论.用户ID

评论.PageID

评论.PostTime

页面标签[]

如果您使用 NosDB (A .NET based NoSQL Database with SQL support),您的查询将类似于

 SELECT * FROM Comments WHERE userid = ‘That user’;

 SELECT * FROM Comments WHERE pageid = ‘That user’;

 SELECT * FROM Comments WHERE post-time > DateTime('2016, 1, 1');

 SELECT * FROM Page WHERE tag = 'kendo'

从他们的 SQL cheat sheet 或文档中检查所有支持的查询类型。


I
Imran Javed

尽管在这种情况下最好使用 RDBMS 而不是 NoSQL,但一种可能的解决方案是维护额外的节点或集合来管理映射和索引。它可能会以额外的集合/节点和处理的形式产生额外的成本,但它将提供易于维护和避免数据冗余的解决方案。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅