MongoDB(noSQL)何时拆分集合

Jes*_*sse 6 mongodb node.js

所以我正在用NodeJS和ExpressJS编写一个应用程序。这是我第一次使用像MongoDB这样的noSQL数据库,并且试图弄清楚如何修复我的数据模型。

在我们的项目开始时,我们已经记录了关系数据库中的所有内容,但是由于我们最近从该项目的Laravel切换到ExpressJS,所以我对处理所有不同的表格布局有些困惑。

到目前为止,我已经知道最好对您的方案进行非规范化,但是它必须在某个地方结束,对吗?最后,您可以将整个数据存储在一个集合中。好吧,不是很有趣,但是你明白了。

1.因此,是否有规则标准定义了在哪里进行切割以进行多个收藏? 我有一个与用户(都是客户或商店用户),商店,产品,购买,类别,子类别的关系数据库。

2.在noSQL数据库中定义关系是否不好? 就像每个产品都有一个类别,但是我想通过一个ID关联该类别(MongoDB中的父工作),但这是一件坏事吗?还是在这里选择性能还是结构?

3. noSQL / MongoDB可以用于具有很大关系(如果它们是在MySQL中创建)的大型数据库吗?

提前致谢

Mar*_*erg 5

如前所述,没有像SQL的第二范式那样的规则。

但是,我将在此处列出一些与MongoDB优化相关的最佳实践和常见陷阱。

过度使用嵌入

BSON限制

与普遍的看法相反,参考文献没有错。假设您有一个图书馆,并且想跟踪租金。您可以从这样的模型开始

{
  // We use ISBN for its uniqueness 
  _id: "9783453031456"
  title: "Schismatrix",
  author: "Bruce Sterling",
  rentals: [
    {
      name:"Markus Mahlberg,
      start:"2015-05-05T03:22:00Z",
      due:"2015-05-12T12:00:00Z"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

尽管此模型存在多个问题,但最重要的问题并不明显- 由于BSON文档的大小限制为16MB ,因此租金数量有限

文件迁移问题

将租金存储在阵列中的另一个问题是,这将导致相对频繁的文档迁移,这是相当昂贵的操作。BSON文档永远不会被分区和创建,它们在增长时会事先分配一些额外的空间。这个额外的空间称为padding。当超出填充范围时,文档将移动到数据文件中的另一个位置,并分配新的填充空间。因此,频繁添加数据会导致频繁的文档迁移。因此,最佳实践是防止频繁的更新增加文档的大小,而改用引用。

因此,对于该示例,我们将更改单个模型并创建第二个模型。一,本书的模型

{
  _id: "9783453031456",
  title:"Schismatrix",
  author: "Bruce Sterling"
}
Run Code Online (Sandbox Code Playgroud)

出租的第二个模型看起来像这样

{
  _id: new ObjectId(),
  book: "9783453031456",
  rentee: "Markus Mahlberg",
  start: ISODate("2015-05-05T03:22:00Z"),
  due: ISODate("2015-05-05T12:00:00Z"),
  returned: ISODate("2015-05-05T11:59:59.999Z")
}
Run Code Online (Sandbox Code Playgroud)

当然,作者或承租人也可以使用相同的方法。

过度规范化的问题

让我们回头看看。开发人员将识别涉及业务案例的实体,定义它们的属性和关系,编写相应的实体类,将头撞墙几个小时,以达到所需的三层内外以上的工作对于用例,此后所有人都过着幸福的生活。那么,为什么一般都使用NoSQL,尤其是MongoDB?因为从此以后没有人过着幸福的生活。这种方法可怕地缩放,几乎唯一的缩放方法是垂直缩放。

但是NoSQL的主要区别在于,您可以根据需要回答的问题对数据进行建模。

话虽如此,让我们看一个典型的n:m关系,并以作者与书籍之间的关系为例。在SQL中,您有3个表:两个表用于您的实体(书籍作者),一个表用于关系(哪本书的作者是谁?)。当然,您可以使用这些表并创建它们的等效集合。但是,由于MongoDB中没有JOIN,因此需要三个查询(一个查询用于第一个实体,一个查询用于其关系,一个查询用于相关实体)以查找实体的相关文档。这是没有道理的,因为n:m关系的三表方法是专门为克服SQL数据库强制执行的严格模式而发明的。由于MongoDB具有灵活的架构,因此第一个问题将是存储关系的位置,同时牢记由于过度使用嵌入而引起的问题。由于作者可能会在未来几年写很多书,但由于一本书的作者身份很少甚至根本没有变化,答案很简单:我们将作者存储为书籍数据中的作者参考

{
  _id: "9783453526723",
  title: "The Difference Engine",
  authors: ["idOfBruceSterling","idOfWilliamGibson"]
}
Run Code Online (Sandbox Code Playgroud)

现在,通过执行以下两个查询,可以找到该书的作者:

var book = db.books.findOne({title:"The Difference Engine"})
var authors = db.authors.find({_id: {$in: book.authors})
Run Code Online (Sandbox Code Playgroud)

我希望以上内容可以帮助您决定何时真正“拆分”您的收藏并避开最常见的陷阱。

结论

关于你的问题,这是我的答案

  1. 如前所述:,但请记住技术限制,应在可能的情况下为您提供一个思路。
  2. 不错-只要它适合您的用例即可。如果您具有给定的类别及其_id,则很容易找到相关产品。加载产品时,您可以轻松获得它所属的类别,甚至可以高效地获得它的类别_id(默认情况下已索引)。
  3. 我还没有找到用MongoDB无法完成的用例,尽管使用MongoDB可能会使事情变得更加复杂。您应该做的是总结功能需求和非功能需求的总和,并检查优势是否大于劣势。我的经验法则:如果您的需求列表中包含“可伸缩性”或“高可用性/自动故障转移”之一,那么MongoDB不仅值得一看。