【问题标题】:Recommendations for MongoDB schema design对 MongoDB 架构设计的建议
【发布时间】:2017-07-08 12:53:19
【问题描述】:

假设您想对某种情况进行建模。公司可以有一个或多个分支机构。这些分支机构的员工可以在不同的公司(甚至同一公司的两个不同的分支机构)工作。这当然只是一个例子。

我们还假设大多数搜索/查询将针对员工和公司集合进行。

第一种(天真的)方法是嵌入所有内容(公司有分支机构,分支机构有员工):

{
    name: "Company name",
    // other company data
    branches : [
        { 
            name: "Branch name",
            // other branch data
            Employees: [
                {
                    // employee1 data
                },
                {
                    // employee data
                },
            ]
        }
    ]
}

但是当人们有兴趣检索员工信息时,这将非常低效(必须检索公司,然后遍历每个分支机构以查找所需的员工)。

另一方面,可以使用引用并模仿 RDBMS(会有 Company、Branch 和 Employee 集合),但这意味着更多的查询。

第三个选项(我最接近)是将 Employee 作为一个单独的集合,然后在 Branches 中有一个对它的引用数组。此外,为了允许更快的查询,例如:“具有特定名称的员工,为特定公司和特定分支机构工作”,Company ObjectId 可以存储在 Employee 集合中:

{
    company_id: "some id",
    first_name: "First name",
    last_name: "Last name",
    //
}

因此,在这种情况下,要搜索为特定公司和特定分支机构工作的具有特定姓名的所有员工,必须进行两次查询。第一个查询将返回满足“公司条件”(公司名称和分支机构名称)的公司,然后对 Employee 集合的第二个查询将返回所有具有指定名称且在其 ID 在第一个查询中返回的公司工作的员工。

您会以其他方式执行此操作吗?有没有其他“推荐”的方式来做到这一点?你会添加一些改进吗?

更重要的是,当这两个查询返回的结果集有小的交集时该怎么办?在这种情况下如何提高性能?

【问题讨论】:

    标签: mongodb nosql


    【解决方案1】:

    我认为您的方向基本正确。

    虽然在某些情况下,MongoDB 中的非规范化并不像关系数据库中那样邪恶,但实际上是正确的做法,但这里有一个案例,您应该使用多个集合。这是因为 MongoDB 文档的上限为 16MB。当你有一家非常大的公司,有很多分支机构,有很多员工,员工子文档变得更加复杂,你可以很容易地突破这个限制。

    让员工推荐公司是个好主意。但是你应该考虑不要使用公司的_id字段,而是使用公司名称和分公司名称,只要你能保证它们的每个组合在公司集合中都是唯一的(比如在这两个上使用唯一的复合索引字段)。原因是当您查找员工时,您通常还需要公司和分支机构的名称。当您只有 _id 时,您必须进行额外的查询才能获得该信息。

    您说分支机构和员工之间没有 1:n 的关系,而是 n:m 的关系。在这种情况下,我建议您为每个员工添加一个“分配”数组,其中包含具有两个字段的对象,company_name 和 company_branch(也许您想添加第三个字段“职位”,说明他或她在做什么那里)。

    您的员工文件将如下所示:

    {
        first_name: "First name",
        last_name: "Last name",
        //
        assignments: [
            { company:"Aperture Science", branch:"R&D", position:"test subject" },
            { company:"Black Mesa", branch:"security", position:"leader of blue shift" }
        ]
    }
    

    请注意,您可以在这里使用无模式数据库的优势:您可以轻松地拥有不仅有分支机构,而且拥有更多层次结构(如部门和组)的公司,而其他公司则没有。

    但是当我想重命名公司或分支机构时怎么办?

    在这种情况下,您必须更新每个引用重命名的公司/分支机构的员工文档。是的,对于这种情况,它不是最有效的模式。但请记住,MongoDB 模式应始终针对最常见的用例进行优化。您认为哪些情况会更频繁地发生:a) 公司或分支机构更名或 b) 有人想查找员工?

    【讨论】:

    • 感谢您的回复。 Company、Branch 和 Employee 只是说明问题的一个例子。我喜欢用 assignments 数组模拟多对多关系。我将使用它并在其中添加所有“可搜索”字段。我不会达到 16MB 的限制,但我正在考虑使用多个集合 - 一个用于 Company(Branch 将嵌入其中),一个用于 Employee。
    猜你喜欢
    • 2011-12-28
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    • 2020-08-07
    • 2012-08-25
    • 2011-05-25
    • 1970-01-01
    相关资源
    最近更新 更多