【问题标题】:Storing data of reverse foreign keys存储反向外键数据
【发布时间】:2014-07-25 17:15:40
【问题描述】:

我想在第一个模型引用的模型中存储模型的一些信息。

考虑我有这些类(省略 ID)

class Student:
    currentClassroom = ForeignKey(Classroom)
    age = Integer

class Classroom:
    totalAgeOfStudents = Integer

因此,如果我将学生添加到教室,那么它的教室也应该更新。在更复杂的情况下,考虑我们还有 Campus、City 和 Province。因此,当一个学生被添加/更新时,新旧教室、教室的校区、校区所在的城市和所在城市的省份也应该更新。这些模型的获取频率很高,因此在这里计算每个请求是不可能的。

在我迁移到 node.js 之前,我曾经在 django(使用 MySQL)中做这样的事情: 每个模型都有一个“计算”方法。每当更新学生时,在此计算方法中,旧教室和新教室都会被标记为脏教室。之后,处理标记为脏的模型,调用它们的计算方法,并相应地设置它们的字段(例如,它们通过查询学生表来计算学生的总年龄),然后如果其他模型也应该改变,它们标记它也很脏。以此类推。

我不认为这种方法很好。我在 django 中尝试了保存/删除/更新钩子(猫鼬也有保存/删除钩子),但情况没有改变:每当我收到一个学生的事件时,我首先更新他/她教室的字段,然后触发教室对应的事件等等。

在猫鼬中有没有更好的方法更有效更好?

赏金编辑:我知道在我的示例中,我可以将教室标记为脏,然后使用 MongoDB 的聚合方法来计算相关字段。我要求更好的方法。

【问题讨论】:

  • 如果有人要投反对票,他/她至少应该解释他/她的理由。
  • 什么是“好”、“不好”、“有效”和“无效”(以及“更有效”)?您似乎在描述一种通用且不可避免的方法:“重新计算相关信息”。 (如果你遗漏了任何东西,它是“最好是渐进式的”。)我们如何描述“不同”和“更好”的东西?如果你从这个描述中为你的旧方法申请专利......要求某人实施它......你认为它是什么以及它的优点和缺点在这里清楚吗? (反问。回答:不。)这个不好的“这个”是什么?这不是什么“好”?
  • nice -> 不涉及低级数据库触发器,即。在服务器代码本身中完成这项工作。有效-> 快速,正如您所说,这意味着最好是渐进式的。我认为对我的旧 django 实现的解释不是不可理解的,尽管太笼统了。为了澄清,我问是否有更快/更好的实现可能。例如,使用 redis 服务器进行 sum 计算。 redis 服务器将存储汇总字段,当发生更改时,相应的 redis 条目会更改(或删除以重新计算)。

标签: database node.js mongoose


【解决方案1】:

tl;dr:通过确定组合表达式上的 dag 然后按 dag 顺序从(部分)基表向上通过共享子表达式到各种输出表(或部分)来更新您的摘要(或其他)基表)。在值得的地方逐步增加。

那个标题……“存储反向外键的数据”

外键具有一定的方向感。但它描述了一个约束。约束是关于数据库的真理。对应于外键约束的命题是表含义方面的蕴涵(->)和表值方面的包含(

就组成表的含义而言,外键与查询的含义无关。正确规范化的数据库没有方向。一个查询表达式,忽略交换运算符的任意排序并承认等价的重新排列,可以被认为是(部分)由内而外排序,即离开。一组查询,因为它们可以共享子表达式,所以定义了一个有向无环图,最外层的查询运算符位于顶部,基表值位于底部。您应该通过此图表进行评估。在可能的情况下,这应该是增量的,并且值得付出努力。例如,如果您知道少数改变的人的债务变化,则无需重新计算所有学生的债务总和。

因此,如果您的方法(除了最笼统的术语以及您的其他不合理的标题所暗示的那样完全不清楚)涉及以下外键,请不要这样做。 关注数据。从基础到查询结果。 FK 仅与此相关,因为它们可能会影响要评估的最佳 dag 以优化表达式共享。 (DBMS 是否会针对同时查询进行优化。)

当你澄清你的问题时,解释你的头衔和特别是 FK 与你的问题有什么关系。尽管也许您认为它们相关与您的不满有关。换句话说,您寻求的重新计算顺序应该是每个查询而不是 FK。

【讨论】:

  • 实际上,您是对的,这是关于优化查询的计算,而不是模型本身。但是每次我获取符合某些条件的教室时,我也希望获得他们的计算字段(总年龄等)。由于我可能有许多教室、校园、城市等,因此就速度而言,计算每个查询并不是一个好主意。由于教室的“学生总年龄”这个概念在某种程度上与教室实例有关,我认为将这些数据存储在模型本身中可能会更好。
  • 顺便说一句,我认为标题很好地解释了这种情况。如果学生与教室有一对多的关系,我们可以说学生对教室有 FK。教室对学生有(虚拟)反向 FK。由于我想在教室的反向 FK 中计算一些数据,所以标题有点解释性。
  • 计算是针对您想要的概念查询。您正在“获取”其结果的请求。您可以在您选择的任何层中计算和/或缓存中间结果。虽然只使用数据库是一个合理的第一个设计。
  • 你写的 FK 很奇怪。 FK 不是字段/列或指针。这是一个约束,即只有一个实例/行与另一个类/表中的给定字段/列匹配。当被告知时,ORM 只给出一个指针而不是包含一个指针的集合。单指针本身不是 FK。 (并且教室没有对学生的 FK。您的意思是“学生占用的教室”(关联/关系)实体,关联/关系是“学生实体占用教室实体”。)请参阅我的回答,FK 有一个 方向感,但约束和查询没有
  • 我并没有暗示教室对学生有 FK。实际上是相反的。而且,由于在定义 FK 时,您为其创建了一个字段(在本例中为 Student.currentClassroom),该字段存储了 FK 对象 (Classroom.id) 的 id。我认为讨论这些术语的定义根本没有帮助。是的,您定义了一个 FK,然后 ORM 为您创建一个指针,或者您可以手动创建一个指向引用对象的字段(通过存储其中一个唯一字段),除了约束之外,它执行完全相同的工作。但这与我的问题完全无关。
猜你喜欢
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
  • 2020-12-27
  • 2019-12-01
  • 1970-01-01
  • 2014-04-08
  • 2016-08-20
  • 2014-06-01
相关资源
最近更新 更多