【问题标题】:Is this structure possible to implement with MongoDB?这种结构可以用 MongoDB 实现吗?
【发布时间】:2016-08-08 10:49:08
【问题描述】:

所以我正在用 Meteor 编写一个应用程序,这是我大学的一个迷你社交网络。我现在面临的问题是我的数据是相关的。 这个网络应用程序允许人们撰写帖子并发布图像和链接。关注该用户的人会在他的 Feed 上看到他的帖子。人们可以分享这个。所以数据是相互关联的。

基本上是这样

  1. 用户有关注者
  2. 关注者从他们关注的人那里获得帖子
  3. 他们可以评论和分享
  4. 分享的帖子会显示在关注分享者的人身上
  5. 每个帖子都应该使用预定义的标签进行标记
  6. 关注标签的人应该得到带有标签的帖子,无论他们是否关注写帖子的人

【问题讨论】:

  • 是的。还有什么好说的?

标签: mongodb meteor social-networking meteor-accounts database


【解决方案1】:

在开始对数据建模之前,您已经完成了定义用例的第一步,也是正确的一步。

但是,您误解了相关数据需要 RDBMS。

model relationships between documents有几种方式。

注意:为了简洁和易于理解,以下示例进行了高度简化

嵌入

可以简单地通过嵌入来建模 1:1 关系:

{
    _id: "joe",
    name: "Joe Bookreader",
    address: {
          street: "123 Fake Street",
          city: "Faketon",
          state: "MA",
          zip: "12345"
        }
}

1:many 关系也可以通过嵌入来建模:

{
    _id: "joe",
    name: "Joe Bookreader",
    phone:[
        { type:"mobile", number:"+1 2345 67890"},
        { type:"home", number:"+1 2345 987654"}
    ]
}

参考文献

与 RDBMS 相比的主要区别在于您在应用程序代码中解析引用,如下所示。

隐式引用

假设我们有出版商和书籍。发布者文档可能如下所示

{
  _id: "acme",
  name: "Acme Publishing, Inc."
}

书籍文档可能看起来像这样

{
  _id:"9788636505700",
  name: "The Book of Foo",
  publisher: "acme"
}

现在重要的部分来了:我们基本上有两个可以用这些数据覆盖的用例。第一个是

对于“The Book of Foo”,获取出版商的详细信息

很简单,因为我们已经有了“The Book of Foo”和它的价值观

db.publishers.find({_id:"acme"})

另一个用例是

Acme Publishing, Inc. 出版了哪些书籍?

既然我们有 Acme Publishing, Inc 的数据,这很容易:

db.books.find({publisher:"acme"})

显式引用

MongoDB有一个引用的概念,通常称为DBRefs

但是,这些引用由驱动程序解析,而不是由 MongoDB 服务器解析。就我个人而言,我从未使用过或不需要它,因为隐式引用在大多数情况下都能完美运行。

“用户发帖”的示例建模

假设我们有一个类似的用户文档

{
  _id: "joe",
  name: "John Bookreader",
  joined: ISODate("2015-05-05T06:31:00Z"),
  …
}

如果天真地这样做,我们只是将帖子嵌入到用户文档中。

但是,这将限制一个人可以发布的帖子数量,因为 BSON 文档的硬编码大小限制为 16MB。

因此,很明显,每个帖子都应该有自己的文档,并注明作者:

{
  _id: someObjectId,
  title: "My first post",
  text: "Some text",
  author: "joe"
}

但是,这带来了一个问题:我们想要显示作者的姓名,而不是他的 ID。 对于单个帖子,我们可以简单地在用户集合中进行查找以获取名称。但是当我们想要显示帖子列表时怎么办?这将需要大量查询。因此,我们使用冗余来保存这些查询并优化我们的应用程序:

{
  _id: someObjectId,
  title: "My first post",
  text: "Some text",
  author: { id:"joe", name: "Joe Bookreader"}
}

因此,对于帖子列表,我们可以将它们与发布者的姓名一起显示,而无需额外查询。只有当用户想要获取有关海报的详细信息时,您才会通过他的 id 查找海报。有了这个,我们为一个常见的用例保存了很多查询。您可能会说“停止!如果用户更改了他的名字怎么办?”好吧,对于初学者来说,这是一个相对罕见的用例。即使在什么时候,这也不是什么大问题。首先,我们必须更新用户文档:

db.users.update({"_id":"joe"},{$set:{name:"Joe A. Bookreader"}})

然后,我们必须采取额外的步骤:

db.posts.update(
    { "author.id": "joe" },
    { $set:{ "author.name": "Joe A. Bookreader" }},
    { multi: true}
)

当然,这有点贵。但是我们在这里做了什么?我们以一个相当罕见的用例为代价优化了一个常见的用例。在我的书中很划算。

我希望这个简单的示例可以帮助您更好地理解如何使用 MongoDB 处理应用程序的用例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-31
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 2021-10-24
    • 2018-10-15
    相关资源
    最近更新 更多