开源ERP Odoo层次数据结构处理原理

Odoo层次结构(parent_left, parent_right)处理原理

Odoo中很多层次结构表,如库位表(stock.location)、Partner表、包裹(stock.operation.package)等表,都有一个parent_id字段指示其上级记录。为了提高层次结构(树状结构)的处理效率,系统中还另外增加了两个字段(parent_left, parent_right),用于快速遍历树状节点。详细原理可以参考这里:之前的《数据库中存储层级结构算法解析》。

开源ERP Odoo层次数据结构处理原理

图片来源:开源智造-OSCG.CN

Odoo中 child_of 操作符充分利用字段(parent_left, parent_right),快速返回下级记录(包括儿子、孙子)。由于种种原因,系统中字段(parent_left, parent_right)有时候会错乱,child_of 不能正确取值,导致一系列奇怪问题。常见问题是,明明有库存,却总是不能保留出库(原因是库位的 parent_left, parent_right 错乱了)。


具体解决办法

Odoo中parent_left 维护着树状结构前序遍历的顺序,parent_right 总是等于 parent_left 加上 子节点数的两倍再加1 。没有子节点的,parent_right = parent_left + 1 , 2个子节点的,parent_right = parent_left + 4 + 1 。如下图所示的库位表结构。

Odoo中child_of 的实现原理是,一个节点的所有下级节点的条件是:parent_left大于当前节点的parent_left, parent_right 小于当前节点的parent_right的所有节点即为下级节点。如果parent_left, parent_right错乱了,child_of 操作就不对,这会导致很多奇怪错误!

系统的base model有一个方法 _parent_store_compute(),用于重算全表的parent_left, parent_right 。 如果parent_left, parent_right错乱了,可以写一个修正的Server Action,一条语句:model._parent_store_compute() ,执行它,重算一下parent_left, parent_right 即OK。

开源ERP Odoo层次数据结构处理原理

图片来源:开源智造-OSCG.CN