package
0.0.0-20240924034108-824aca03167b
Repository: https://github.com/fox-gonic/database.git
Documentation: pkg.go.dev
# README
Nested Set for Go
Nested Set is an implementation of the Nested set model for Gorm.
This project is the Go version of awesome_nested_set, which uses the same data structure design, so it uses the same data together with awesome_nested_set.
Actually the original design is for this, the content managed by awesome_nested_set in our Rails application, the front-end Go API also needs to be maintained.
This is a Go version of the awesome_nested_set, and it built for compatible with awesome_nested_set.
Usage
Define the model
You must use nestedset
Stuct tag to define your Gorm model like this:
Support struct tags:
id
- int64 - Primary key of the nodeparent_id
- sql.NullInt64 - ParentID column, null is rootlft
- intrgt
- intdepth
- int - Depth of the nodechildren_count
- Number of children
Optional:
scope
- restricts what is to be considered a list. You can also setup scope by multiple attributes.
Example:
import (
"database/sql"
"github.com/fox-gonic/fox/database/nestedset"
)
// Category
type Category struct {
ID int64 `gorm:"PRIMARY_KEY;AUTO_INCREMENT" nestedset:"id"`
ParentID sql.NullInt64 `nestedset:"parent_id"`
UserType string `nestedset:"scope"`
UserID int64 `nestedset:"scope"`
Rgt int `nestedset:"rgt"`
Lft int `nestedset:"lft"`
Depth int `nestedset:"depth"`
ChildrenCount int `nestedset:"children_count"`
Title string
}
Move Node
import nestedset "github.com/fox-gonic/fox/database/nestedset"
// create a new node root level last child
nestedset.Create(tx, &node, nil)
// create a new node as parent first child
nestedset.Create(tx, &node, &parent)
// nestedset.MoveDirectionLeft
// nestedset.MoveDirectionRight
// nestedset.MoveDirectionInner
nestedset.MoveTo(tx, node, to, nestedset.MoveDirectionLeft)
Get Nodes with tree order
// With scope, limit tree in a scope
tx := db.Model(&Category{}).Where("user_type = ? AND user_id = ?", "User", 100)
// Get all nodes
categories, _ := tx.Order("lft asc").Error
// Get root nodes
categories, _ := tx.Where("parent_id IS NULL").Order("lft asc").Error
// Get childrens
categories, _ := tx.Where("parent_id = ?", parentCategory.ID).Order("lft asc").Error
Testing
$ createdb nested-set-test
$ go test ./...
-- some useful sql to check status
SELECT n.id,
CONCAT(REPEAT('. . ', (COUNT(p.id) - 1)::int), n.title) AS t,
n.title, n.lft, n.rgt, n.depth, n.children_count
FROM categories AS n, categories AS p
WHERE (n.lft BETWEEN p.lft AND p.rgt)
GROUP BY n.id ORDER BY n.lft;
License
MIT
# Functions
Create a new node within its parent by Gorm original Create() method ```nestedset.Create(db, &Category{...}, nil)``` will create a new category in root level ```nestedset.Create(db, &Category{...}, &parent)``` will create a new category under parent node as its last child.
Delete a node from scoped list and its all descendent ```nestedset.Delete(db, &Category{...})```.
MoveTo move node to a position which is related a target node ```nestedset.MoveTo(db, &node, &to, nestedset.MoveDirectionInner)``` will move [&node] to [&to] node's child_list as its first child.
Rebuild rebuild nodes as any nestedset which in the scope ```nestedset.Rebuild(db, &node, true)``` will rebuild [&node] as nestedset.
# Constants
MoveDirectionInner : MoveTo(db, a, n, MoveDirectionInner) => [n [...|a]].
MoveDirectionLeft : MoveTo(db, a, n, MoveDirectionLeft) => a|n|...
MoveDirectionRight : MoveTo(db, a, n, MoveDirectionRight) => ...|n|a|.
# Type aliases
MoveDirection means where the node is going to be located.