我有一个MySQL数据库来支持多语言网站,其中的数据表示如下:
表1
id
is_active
created
table1_lang
table1_id
name
surname
address
在mongo数据库上实现相同目标的最佳方式是什么?
答案 0 :(得分:3)
您可以设计可以引用或嵌入文档的架构。我们来看看嵌入式文档的第一个选项。在上面的应用程序中,您可以将信息存储在文档中,如下所示:
// db.table1 schema
{
"_id": 3, // table1_id
"is_active": true,
"created": ISODate("2015-04-07T16:00:30.798Z"),
"lang": [
{
"name": "foo",
"surname": "bar",
"address": "xxx"
},
{
"name": "abc",
"surname": "def",
"address": "xyz"
}
]
}
在上面的示例模式中,您基本上会在主table1_lang
文档中嵌入table1
信息。这种设计有其优点,其中之一就是数据局部性。由于MongoDB将数据连续存储在磁盘上,因此将所需的所有数据放在一个文档中可确保旋转磁盘在搜索磁盘上的特定位置时花费的时间更少。如果您的应用程序经常访问table1
信息以及table1_lang
数据,那么您几乎肯定会想要使用嵌入式路由。嵌入式文档的另一个优点是写入数据时的原子性和隔离性。为了说明这一点,假设您要删除一个文本,该文档具有值为“foo”的lang键“name”,这可以通过一个(原子)操作来完成:
db.table.remove({"lang.name": "foo"});
有关MongoDB中数据建模的更多详细信息,请阅读文档 Data Modeling Introduction ,特别是 Model One-to-Many Relationships with Embedded Documents
另一个设计选项是引用遵循规范化架构的文档。例如:
// db.table1 schema
{
"_id": 3
"is_active": true
"created": ISODate("2015-04-07T16:00:30.798Z")
}
// db.table1_lang schema
/*
1
*/
{
"_id": 1,
"table1_id": 3,
"name": "foo",
"surname": "bar",
"address": "xxx"
}
/*
2
*/
{
"_id": 2,
"table1_id": 3,
"name": "abc",
"surname": "def",
"address": "xyz"
}
上述方法提高了执行查询的灵活性。例如,要为ID为3的主要父实体table1_lang
检索所有子table1
文档将很简单,只需针对集合table1_lang
创建一个查询:
db.table1_lang.find({"table1_id": 3});
当您与非常不可预测的arity建立一对多关系时,使用文档引用方法的上述规范化模式也具有优势。如果每个给定table_lang
实体有数百或数千个table
文档,则就空间约束而言,嵌入有如此多的挫折,因为文档越大,它使用的RAM越多,MongoDB文档就越多硬度限制为16MB。
一般的经验法则是,如果您的应用程序的查询模式是众所周知的,并且数据往往只能以一种方式访问,那么嵌入式方法效果很好。如果您的应用程序以多种方式查询数据,或者您无法预测数据查询模式,则更为规范化的文档引用模型将适用于此类情况。
价: