Nested Set Model (or Modified Preorder Tree) represents nested sets (trees or hierarchies) in relational databases. See wikipedia.
The nested model:
- assigns two numbers for each node as left and right, that
- left of each node is less than all its children's left, and
- right of each node is greater than all its children's right.
Numbers could be assigned according to a preorder tree traversal, which visits each node twice, and assigns numbers at both visits.
- Then querying all descendants of a node could be efficiency as:
SELECT child.id, child.node, child.lft, child.rgt
FROM `nested` parent, `nested` child
WHERE child.lft BETWEEN parent.lft AND parent.rgt
AND parent.id=@node_id
- And querying the path from root to any node could be:
SELECT parent.id, parent.node, parent.lft, parent.rgt
FROM `nested` parent, `nested` child
WHERE child.lft BETWEEN parent.lft AND parent.rgt
AND child.id=@node_id
ORDER BY parent.lft
- Another column
depth
is used to record depth of the node, to query immediate children of a node efficiently, and the querying could be:
SELECT child.id, child.node, child.lft, child.rgt
FROM `nested` parent, `nested` child
WHERE child.lft BETWEEN parent.lft AND parent.rgt
AND child.depth=parent.depth+1
AND parent.id=@node_id
The nested model is also suitable for trees with more than one root, forests.
Test data used in nested_test.go
are collected from previous wikipedia article.
- Clothing
- Men's
- Suits
- Slacks
- Jackets
- Women's
- Dresses
- Evening Gowns
- Sun Dresses
- Skirts
- Blouses
Traversal and number nodes as:
Store Chinese division data with nested sets:
- build a division tree from raw data,
- assign left and right number for divisions by preorder tree traversal,
- generate sql inserting queries
Data collected from **行政区划数据. Initial inserting SQL in division.sql
are generated with build.go
:
$ cd division && go run build.go # generates data inserting sql
Store product category info and structure with nested sets:
- run
spider/spider.py
to query data from t**, - build sql inserting data
data/categoryInfo.sql
anddata/categoryTree.sql
as inbuild_test.go
- create new table as in
createtable.sql
with your table name; - initialize table as in
division/build.go
, or - call
Add...()
continually as inTestInserting()
; - call
SetTableName()
in yourinit()
;