[英]Many-to-many relationship with NoSQL database
我想为我的带有NoSQL数据库的node.js应用程序实现分类结构(地理术语)。 我有一个与MySQL类似的分类结构,但现在是时候向前推进并学习新东西,所以我决定尝试不同的方法并使用NoSQL(面向文档)来测试我的测试应用程序。 分类结构很简单 - 有五个不同的级别:国家( 即英国)→地区(英格兰)→县(默西塞德郡)→城市/城镇/村庄(利物浦)→城市的一部分(Toxteth)。
显而易见的选择是使用树木结构,但魔鬼在细节 - 历史上一些城市和城镇属于其他县。 这个想法是用那些术语来标记出生在某些城市或城镇的人,然后用地理标记过滤它们,所以我必须尊重利物浦或曼彻斯特(以及其他人)在某些人出生时属于兰开夏郡的事实。 。 否则,任何用户使用我的地理过滤器获得的结果都将是错误的。
例如:约翰·多伊于1957年出生于布莱克本(兰开夏郡)。保罗·布朗1960年出生于利物浦(兰开夏郡,现为默西塞德郡)。 Georgia Doe(nee Jones)5年后出生在威勒尔(柴郡,现在的默西塞德郡)。 他们的儿子林戈于1982年出生于利物浦(默西塞德郡)。
约翰是兰开斯特出生的,保罗是兰开斯特和梅西大学,格鲁吉亚同时来自柴郡和默西塞德郡,林戈来自默西塞德郡。 所以当我按县搜索时,应该对它们进行相应的分类。 但是,随着国家现代结构的简单一对多结构,他们永远不会被过滤掉。
如何使用NoSQL(首先是面向文档的)解决方案来实现集合的复杂性? 我用Google搜索并对堆栈进行了一些研究*但仍然不知道下一步该做什么。 在我看来,有几种可能的解决方法:
使用类似SQL的数据结构:
{ {'name': 'United Kingdom', 'unique_id': 1}, {'name': 'England', 'unique_id': 2, 'parents': [1]}, {'name': 'Merseyside', 'unique_id': 3, 'parents': [2]}, {'name': 'Lancashire', 'unique_id': 4, 'parents': [2]}, {'name': 'Liverpool', 'unique_id': 5, 'parents': [3, 4]}, }
使用树结构和一些引用:
{ {'name': 'United Kingdom', 'unique_id': 1 {'name': 'England', 'unique_id': 2] {'name': 'Merseyside', 'unique_id': 3] {'name': 'Liverpool', 'unique_id': 5, 'alternate_parents': [4]}, }, {'name': 'Lancashire', 'unique_id': 4}, }, }, }
使用没有引用的树结构(一对多)并手动将“alternate parent”标记添加到文档中:
{ {'name': 'United Kingdom', 'unique_id': 1 {'name': 'England', 'unique_id': 2] {'name': 'Merseyside', 'unique_id': 3] {'name': 'Liverpool', 'unique_id': 5}, }, {'name': 'Lancashire', 'unique_id': 4}, }, }, }
坚持使用SQL。
请告诉我这方面的建议。 我是任何NoSQL的新手(目前我没有设计过这样的数据库),所以对我来说有一个真正的设计问题。
我是新手堆叠*所以如果我对这篇文章做错了,请随时纠正我:)谢谢!
编辑我选择@Jonathan答案作为解决方案。 我认为它更适合我的需求(我的数据库中会存储其他文档并使用这些术语标记它们),尤其是@Valentyn建议的mapReduce功能。
但是,如果您的应用程序不需要文档集合,则@Philipp建议的图形数据库(基于关系而非文档)可能是最佳解决方案。
由于您所做的评论,我认为当您说“NoSQL”时,您的意思是“MongoDB”。 有许多其他数据库技术通常被称为NoSQL,它们完全不同,但这个技术似乎就是你的意思。
这不是一个好主意,因为要获得整个分类链,您需要进行多个数据库查询,这通常应该避免。
3.单个文档是一棵巨大的树也不是一个好主意,因为MongoDB每个文档的限制为16MB。 当您创建巨大的单片文档时,您可能会达到该限制。
我认为MongoDB可能不是您用例的最佳解决方案。 你考虑使用图形数据库吗? MongoDB针对独立的文档进行了优化,这些文档独立存在。 但是图形数据库的重点是数据集,在这些数据集中,你有很多实体,这些实体是由它们与其他实体的关系定义的。 这看起来很像你的用例。
首先,如果您不熟悉基本原则,那么在NoSQL和SQL数据库之间进行选择是很困难的。 如果这是您存储的唯一数据,请使用关系(SQL)。 如果有更多的数据(我假设)并且它需要更多的交织模式,那么坚持使用NoSQL。
我会采取关于此的关系路线,以防止它变得太复杂...开始几个集合; 一个国家,地区等。 不要气馁在NoSQL数据库中执行关系(SQL)类型模式; 大多数时候,他们是最好的解决方案。
然后,在每个子组中,具有命名父节点的字段。
例如:
{
{'name': 'United Kingdom'},
{'name': 'United States'}
}
{
{'name': 'England', 'parent': 'United Kingdom'},
{'name': 'California', 'parent': 'United States'}
}
这样,您的数据集不会嵌套到返回的数据无法管理。 然后你可以轻松地抓住国家和相应的地区......等等。
祝你好运!
编辑:回答OP的问题:
(首先,我推荐MongoDB - 它是一个很好的解决方案。)
因为当你开始使用MongoDB时,你会发现它将数据并排存储在硬盘上。 如果您编辑这样一个巨大的记录,它很可能被推到磁盘的后面,使您的硬盘类似于瑞士奶酪。 一旦达到这一点,你将不得不进行修复以再次压缩它。 此外,通过这种方式,数据在应用程序中更容易分离,这样,如果您需要对数据执行某些操作,则不必将其应用于整个对象。 我假设您将拥有一个大型数据集,因为世界上有许多不同的位置。
不要太担心这种事情。 如果您计划大量更改名称,则可以将ID用于父级,并将子级与ID匹配。 我只是这样做,因为我假设你不需要更改位置数据库。
我会使用嵌套文档来存储多个父项,而不是数组。 这样,可以更容易地查询和索引。 我会使用以下方法:
{ { 'name': 'England, 'parent': { 1: 1, 568: 1 } } }
这样你就可以使用你的索引想法并找到db.region.$.568
= 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.