【问题标题】:Sub-structures vs Flat Data-Structure in MongoDB - NoSQLMongoDB 中的子结构与平面数据结构 - NoSQL
【发布时间】:2019-02-18 00:24:50
【问题描述】:

我尝试了解如何以最佳方式构建 MongoDB 模式,因此寻求指导,尤其是有关使用子结构(嵌入式文档)与平面数据结构的指南。

假设我们想在 MongoDB 中存储一个用户帐户。用户只有一个地址,因此我们可以选择以下两种结构之一:

{ 
_id: String,
username: String,
firstname: String,
surname: String,
email: String,
street: String,
city String,
zip: Number,
}

{
_id: String,
name: {
    first: String,
    last: String,
    }
email: String,
address: {
    street: String,
    city String,
    zip: Number,
    }
}

每种结构的优点/缺点是什么。是否有规则何时使用子结构或何时使用平面结构?一个反对另一个的理由是什么?

提前谢谢你!

【问题讨论】:

    标签: mongodb data-structures nosql data-modeling


    【解决方案1】:

    MongoDB 中提供了各种数据建模模式和模式设计。我将分享我的经验,我遇到了哪些问题以及不同的 DB 模式有什么好处。我们将在下面一一讨论:

    1. 嵌入式 VS 平面数据结构:在这种情况下,两种模式之间没有太大区别,但在嵌入式形式的数据模型的情况下,我们将相似类型的数据分组,以便进行查询当您将 $project 来自任何集合的数据时,有点容易或体积小。

      例如:如果你想获取完整的地址,那么在嵌入文档的情况下,你不需要单独 $project 地址字段,如果你想在获取文档时跳过地址字段,那么你不需要跳过地址字段个人。

    2. 嵌入式(一对一)VS 嵌入式(一对多):当我们讨论嵌入式文档对平面数据结构的好处时,如果我们的用户拥有更多,那么一个地址,然后我们需要查找具有一对多关系的嵌入式文档。
      定义一对一和一对多关系的架构如下:

    一对一关系架构:

    {
    _id: String,
    name: {
        first: String,
        last: String,
        }
    email: String,
    address: {
        street: String,
        city String,
        zip: Number,
        }
    }
    

    一对多关系模式:

      {
        _id: String,
        name: {
            first: String,
            last: String,
            }
        email: String,
        address: [{           // Embedded address doc with one to many relationship
            street: String,
            city String,
            zip: Number,
          }]
      }
    

    在一对一关系的情况下,它不会对您的查询部分产生太大影响,但是如果您使用一对多关系,那么您的查询将会有很多概念上的变化。

    例如:因为主要是我们在更新两种数据结构时面临不同的场景,所以我将分享更新查询之间的区别。

    要更新嵌入一对一关系的数据,您可以简单地使用点表示法。

    db.collection.update(
       { _id: 'anyId' },
       { $set: { "address.street": "abc" } }
    )   
    

    要更新嵌入一对多关系的数据,您需要使用 $ 运算符。在这个有两种不同的情况。首先,如果要更新子文档的特定元素,其次,如果要更新所有子文档:

    案例 1 查询将是(使用 $ operator):

      db.collection.update(
           { 'address.streent': 'abc' },
           { $set: { "address.$.street": "xyz" } }
      )   
    

    案例 2 查询将是(使用 $[]):

      db.collection.update(
           { 'address.streent': 'abc' },
           { $set: { "address.$[]": "xyz" } }
      )  
    

    【讨论】:

    • 非常感谢!嵌入式与平面的查询示例是一个有意义的关键考虑因素!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 2016-05-24
    • 1970-01-01
    相关资源
    最近更新 更多