MongoDB中嵌入与链接:何时嵌入何时链接?

5 投票
2 回答
3232 浏览
提问于 2025-04-17 06:54

我看了这个页面,但还是不太明白什么时候应该用嵌入(embedding)功能,什么时候又该用链接(linking)。我在做一个django项目,使用的是MongoDB。在我的models.py文件里,有以下这些模型:

class Projects(models.Model):
    projectName =models.CharField(max_length = 100,unique=True,db_index=True)
    projectManager = EmbeddedModelField('Users')

class Teams(models.Model):
    teamType = models.CharField(max_length =100)
    teamLeader = EmbeddedModelField('Users')
    teamProject = EmbeddedModelField('Projects')
    objects = MongoDBManager()

class Users(models.Model):
    name = models.CharField(max_length = 100,unique=True)
    designation = models.CharField(max_length =100 )
    teams = ListField(EmbeddedModelField('Teams'))



class Tasks(models.Model):
    title = models.CharField(max_length = 150)
    description = models.CharField(max_length=1000)
    priority = models.CharField(max_length=20)
    Status = models.CharField(max_length=20)
    assigned_to = EmbeddedModelField('Users')
    assigned_by = EmbeddedModelField('Users')
    child_tasks = ListField()
    parent_task = models.CharField(max_length = 150)

我的问题是,如果我们使用嵌入的话,是否需要在所有模型中都更新这个对象。比如说,如果我想更新一个'用户'的名字,我是不是需要在项目(Projects)、团队(Teams)、用户(Users)和任务(Tasks)这些模型里都进行更新,还是说用链接会更好一些呢?

2 个回答

4

在你的例子中,是的,改变用户的名字意味着如果你使用嵌入式存储,那么你必须额外更新所有其他文档。这种情况下,更合适的做法是使用链接(引用)。虽然在查询时需要多一步,但因为你的“业务逻辑”,这样做会更好。

一般来说,如果一个文档需要从多个地方访问,那么把它做成引用而不是嵌入式存储是更合理的选择。当文档经常变化时,情况也是一样的。

3

首先,从概念上来说,给你的模型类起名字时要用单数形式。

用户应该叫做 User,团队应该叫做 Team……

可以把模型想象成一个模具,利用这个模具可以制作出多个对象。User 模型会生成多个 Users,并且会存储在一个叫做 Users 的表里,每一行/文档都是一个 User 对象。

关于你的问题,hymloth 说得完全正确。要把某个字段变成对文档的引用,而不是嵌入式的,可以把这些特定的字段改成引用用户集合中用户的 ID。这样你就只存储一个 ID 来查找,而不是用户文档的副本。当你更改引用的文档时,所有引用这个文档的地方都会一起更新。(这就是典型的关系型关联)

我在 Django-mongoDB 中也没看到有这个字段,但也许你可以用传统的 Django ForeignKey 字段来实现这个目的。我不确定你能否混合使用,所以可以试试看。

例如,你的 Teams 类可以有这样的字段:

teamLeader = ForeignKey(User)

如果这样有效,请告诉我。

撰写回答