何时使用嵌入式文件MongoDB

时间:2021-08-20 15:41:07

After reading the guide for using embedded documents in MongoDB I am still a bit confused as to what they are used for when modelling one-to-one relationships. For example if I had a user which had a username an email and an address which contained street, city, state and zip. Why would I model it like:

在阅读了在MongoDB中使用嵌入式文档的指南之后,我仍然对于在建立一对一关系时使用它们的方式感到困惑。例如,如果我有一个用户,其用户名是电子邮件,地址包含街道,城市,州和邮政编码。我为什么要模仿它:

{
  username: "joe",
  email: "joe@example.com",
  address: {
    street: "123 example rd",
    city: "Faketon",
    state: "MA",
    zip: 1234
  }
}

when I could do something like this which would often save quite a bit of code when saving and loading from the database:

当我可以做这样的事情时,从数据库保存和加载时通常会节省相当多的代码:

{
  username: "joe",
  email: "joe@example.com",
  street: "123 example rd",
  city: "Faketon",
  state: "MA",
  zip: 1234
}

Are there and what are the benefits to using embedded documents for one-to-one relationships? Does it give you any more flexibility or speed with queries? Are there any negative aspects of using embedded documents like this?

使用嵌入式文档进行一对一关系有什么好处?它是否为您提供更多的查询灵活性或速度?使用这样的嵌入式文档是否有任何负面影响?

2 个解决方案

#1


There are several helpful side effects when using embedded documents vs flattening the structure for 1:1 relationships:

使用嵌入式文档时,有几个有用的副作用,而不是将结构展平为1:1关系:

  • You can specify embedded document in query projections, which saves writing code to get sets of related fields and can help reduce network overhead if your application often works with subsets of the full document.
  • 您可以在查询投影中指定嵌入式文档,这样可以节省编写代码以获取相关字段集,并且如果您的应用程序经常使用完整文档的子集,则可以帮助减少网络开销。

Using your first example document:

使用您的第一个示例文档:

{
  username: "joe",
  email: "joe@example.com",
  address: {
    street: "123 example rd",
    city: "Faketon",
    state: "MA",
    zip: 1234
  }
}

You can easily get all of the address fields by projecting the subdocument:

您可以通过投影子文档轻松获取所有地址字段:

> db.user.find({}, {address:1})
{
  "_id": ObjectId("554a0656f5549fd193161e2e"),
  "address": {
    "street": "123 example rd",
    "city": "Faketon",
    "state": "MA",
    "zip": 1234
  }
}
  • Embedded documents can provide additional semantic context.
  • 嵌入式文档可以提供额外的语义上下文。

Looking at your second example it may not be clear to another developer whether state is meant to be used as part of an address or if it might represent an application state (i.e. one arbitrary interpretation might be "MA" => "Management Approval"). The semantics can get harder to infer as are more fields are added to schema over time, or in cases where some of the fields may not be present in all documents.

看看你的第二个例子,另一个开发人员可能不清楚状态是否意味着用作地址的一部分,或者它是否可能代表一个应用程序状态(即一个任意解释可能是“MA”=>“管理批准”) 。随着时间的推移,或者在某些字段可能不存在于所有文档中的情况下,语义可能变得更难以推断。

Similarly, if you wanted to add home and office addresses both could have identical fields:

同样,如果您想添加家庭和办公室地址,则两者可以具有相同的字段:

{
  "home": {
    "street": "123 example rd",
    "city": "Faketon",
    "state": "MA",
    "zip": 1234
  },
  "work": {
    "street": "456 Longcommuta Way",
    "city": "Busyville",
    "state": "CA",
    "zip": 90210
  }
}

You could take advantage of the similarity in subdocuments to have reusable code that works with either home or work addresses.

您可以利用子文档中的相似性来获得可与家庭或工作地址一起使用的可重用代码。

#2


There won't be any performance difference. Both solutions are valid, but you should consider how you'll handle data with your programming language.

不会有任何性能差异。这两种解决方案都是有效的,但您应该考虑如何使用编程语言处理数据。

Example: with PHP or Java classes, you may want to create two classes, User and Address. Address will be embed in your User class/document. You may also want to reuse the Address class/document elsewhere.

示例:使用PHP或Java类,您可能需要创建两个类,User和Address。地址将嵌入您的用户类/文档中。您可能还希望在其他地方重用Address类/文档。

You can see Mongo documents as PHP/Java classes.

您可以将Mongo文档视为PHP / Java类。

#1


There are several helpful side effects when using embedded documents vs flattening the structure for 1:1 relationships:

使用嵌入式文档时,有几个有用的副作用,而不是将结构展平为1:1关系:

  • You can specify embedded document in query projections, which saves writing code to get sets of related fields and can help reduce network overhead if your application often works with subsets of the full document.
  • 您可以在查询投影中指定嵌入式文档,这样可以节省编写代码以获取相关字段集,并且如果您的应用程序经常使用完整文档的子集,则可以帮助减少网络开销。

Using your first example document:

使用您的第一个示例文档:

{
  username: "joe",
  email: "joe@example.com",
  address: {
    street: "123 example rd",
    city: "Faketon",
    state: "MA",
    zip: 1234
  }
}

You can easily get all of the address fields by projecting the subdocument:

您可以通过投影子文档轻松获取所有地址字段:

> db.user.find({}, {address:1})
{
  "_id": ObjectId("554a0656f5549fd193161e2e"),
  "address": {
    "street": "123 example rd",
    "city": "Faketon",
    "state": "MA",
    "zip": 1234
  }
}
  • Embedded documents can provide additional semantic context.
  • 嵌入式文档可以提供额外的语义上下文。

Looking at your second example it may not be clear to another developer whether state is meant to be used as part of an address or if it might represent an application state (i.e. one arbitrary interpretation might be "MA" => "Management Approval"). The semantics can get harder to infer as are more fields are added to schema over time, or in cases where some of the fields may not be present in all documents.

看看你的第二个例子,另一个开发人员可能不清楚状态是否意味着用作地址的一部分,或者它是否可能代表一个应用程序状态(即一个任意解释可能是“MA”=>“管理批准”) 。随着时间的推移,或者在某些字段可能不存在于所有文档中的情况下,语义可能变得更难以推断。

Similarly, if you wanted to add home and office addresses both could have identical fields:

同样,如果您想添加家庭和办公室地址,则两者可以具有相同的字段:

{
  "home": {
    "street": "123 example rd",
    "city": "Faketon",
    "state": "MA",
    "zip": 1234
  },
  "work": {
    "street": "456 Longcommuta Way",
    "city": "Busyville",
    "state": "CA",
    "zip": 90210
  }
}

You could take advantage of the similarity in subdocuments to have reusable code that works with either home or work addresses.

您可以利用子文档中的相似性来获得可与家庭或工作地址一起使用的可重用代码。

#2


There won't be any performance difference. Both solutions are valid, but you should consider how you'll handle data with your programming language.

不会有任何性能差异。这两种解决方案都是有效的,但您应该考虑如何使用编程语言处理数据。

Example: with PHP or Java classes, you may want to create two classes, User and Address. Address will be embed in your User class/document. You may also want to reuse the Address class/document elsewhere.

示例:使用PHP或Java类,您可能需要创建两个类,User和Address。地址将嵌入您的用户类/文档中。您可能还希望在其他地方重用Address类/文档。

You can see Mongo documents as PHP/Java classes.

您可以将Mongo文档视为PHP / Java类。