materialized

package module
v0.0.0-...-5b2fb0d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2025 License: MIT Imports: 7 Imported by: 0

README

Materialized Path Tree Library

The materialized library is a Go module that provides tools to manage hierarchical (tree-like) data structures in a relational database using the materialized path pattern. It integrates seamlessly with GORM for ORM functionality and uses ULID for generating unique node identifiers. The library is designed with multi-tenancy support, allowing isolated tree structures for different tenants (e.g., organizations or users).

Materialized paths represent a tree by storing the full path from the root to each node as a string (e.g., /node1/node2). This approach optimizes queries for hierarchical operations like finding ancestors or descendants.

Features

  • Node Management: Create, update, move, and delete nodes in the tree.
  • Querying: Retrieve nodes by ID, code, or path; fetch ancestors, descendants, or direct children.
  • Multi-Tenancy: Isolate trees by tenant using TenantID and TenantType.
  • Polymorphic Ownership: Associate nodes with owners using OwnerID and OwnerType.
  • Metadata: Store arbitrary key-value data with nodes using JSON-serialized Metadata.
  • Efficient Hierarchical Queries: Leverage materialized paths for fast tree traversal.
  • Unique Identifiers: Generate ULIDs for each node via the Code field.

Installation

To install the library, run:

go get github.com/alifakhimi/materialized

Usage

Setting Up the Database

First, establish a database connection using GORM and create a TreeQuery instance to interact with the tree.

package main

import (
 "github.com/alifakhimi/materialized"
 "gorm.io/driver/sqlite" // Use your preferred database driver
 "gorm.io/gorm"
)

func main() {
 // Connect to the database (SQLite in this example)
 db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
 if err != nil {
  panic("failed to connect to database")
 }

 // Initialize TreeQuery with default configuration
 config := materialized.DefaultTableConfig()
 treeQuery, err := materialized.NewTreeQuery(db, config)
 if err != nil {
  panic("failed to create tree query")
 }

 // Create the database schema (table and indexes)
 if err := treeQuery.CreateSchema(); err != nil {
  panic("failed to create schema")
 }
}

Supported databases include any GORM-compatible database (e.g., SQLite, PostgreSQL, MySQL). Adjust the driver and DSN accordingly.

Creating Nodes

Nodes are created under a parent path. The root node for each tenant is automatically created when accessed via GetRootNode.

// Define tenant identifiers
tenantID := uint(1)
tenantType := "organizations"

// Get or create the root node
rootNode, err := treeQuery.GetRootNode(tenantID, tenantType)
if err != nil {
 panic("failed to get root node")
}

// Create a child node under the root
childNode, err := treeQuery.CreateNode(
 "Child Node",
 rootNode.Path, // "/"
 tenantID,
 tenantType,
 0, // ownerID (optional)
 "", // ownerType (optional)
 map[string]interface{}{
  "description": "A child node under the root",
 },
)
if err != nil {
 panic("failed to create child node")
}
  • Root Path: The root node's path is /.
  • Child Paths: A child of the root has a path like nodeID, and deeper nodes have paths like nodeID1/nodeID2.
Querying the Tree

The library provides methods to query the tree structure:

// Get a node by its unique code
node, err := treeQuery.GetNodeByCode(childNode.Code, tenantID, tenantType)
if err != nil {
 panic("failed to get node by code")
}

// Get direct children of the root
children, err := treeQuery.GetChildrenByPath(rootNode.Path, tenantID, tenantType)
if err != nil {
 panic("failed to get children")
}

// Get all descendants of the root
descendants, err := treeQuery.GetDescendants(rootNode.Path, tenantID, tenantType)
if err != nil {
 panic("failed to get descendants")
}

// Get ancestors of a node
ancestors, err := treeQuery.GetAncestors(childNode.Path, tenantID, tenantType)
if err != nil {
 panic("failed to get ancestors")
}
Moving Nodes

Move a node and its subtree to a new parent:

// Move childNode to a new parent (e.g., root)
err = treeQuery.MoveNode(childNode.Path, rootNode.Path, tenantID, tenantType)
if err != nil {
 panic("failed to move node")
}
Deleting Nodes

Delete a node with or without its descendants:

// Delete childNode and its descendants
err = treeQuery.DeleteNode(childNode.Path, tenantID, tenantType, true)
if err != nil {
 panic("failed to delete node")
}
Searching Nodes

Search nodes by name:

nodes, total, err := treeQuery.SearchNodes("Child", tenantID, tenantType, 10, 0)
if err != nil {
 panic("failed to search nodes")
}
for _, n := range nodes {
 println(n.Name, string(n.Path))
}
println("Total matches:", total)

Configuration

Customize the table and column names using TableConfig:

config := materialized.TableConfig{
 TableName:        "custom_tree",
 PathColumn:       "hierarchy_path",
 TenantIDColumn:   "org_id",
 TenantTypeColumn: "org_type",
 OwnerIDColumn:    "user_id",
 OwnerTypeColumn:  "user_type",
}

treeQuery, err := materialized.NewTreeQuery(db, config)
if err != nil {
 panic("invalid configuration")
}

The default configuration (DefaultTableConfig) uses:

  • Table: tree_nodes
  • Columns: path, tenant_id, tenant_type, owner_id, owner_type

Comprehensive Example

This example demonstrates setting up a tree, creating nodes, moving them, and querying the structure:

package main

import (
 "fmt"

 "github.com/alifakhimi/materialized"
 "gorm.io/driver/sqlite"
 "gorm.io/gorm"
)

func main() {
 // Database setup
 db, err := gorm.Open(sqlite.Open("tree.db"), &gorm.Config{})
 if err != nil {
  panic("failed to connect")
 }

 treeQuery, err := materialized.NewTreeQuery(db, materialized.DefaultTableConfig())
 if err != nil {
  panic("failed to initialize")
 }

 if err := treeQuery.CreateSchema(); err != nil {
  panic("failed to create schema")
 }

 // Tenant setup
 tenantID := uint(1)
 tenantType := "organizations"

 // Get root node
 root, err := treeQuery.GetRootNode(tenantID, tenantType)
 if err != nil {
  panic("failed to get root")
 }
 fmt.Printf("Root: %s (%s)\n", root.Name, root.Path)

 // Create nodes
 nodeA, err := treeQuery.CreateNode("Node A", root.Path, tenantID, tenantType, 0, "", nil)
 if err != nil {
  panic("failed to create Node A")
 }
 fmt.Printf("Node A: %s (%s)\n", nodeA.Name, nodeA.Path)

 nodeB, err := treeQuery.CreateNode("Node B", root.Path, tenantID, tenantType, 0, "", nil)
 if err != nil {
  panic("failed to create Node B")
 }
 fmt.Printf("Node B: %s (%s)\n", nodeB.Name, nodeB.Path)

 nodeC, err := treeQuery.CreateNode("Node C", nodeA.Path, tenantID, tenantType, 0, "", nil)
 if err != nil {
  panic("failed to create Node C")
 }
 fmt.Printf("Node C: %s (%s)\n", nodeC.Name, nodeC.Path)

 // List descendants of root
 descendants, err := treeQuery.GetDescendants(root.Path, tenantID, tenantType)
 if err != nil {
  panic("failed to get descendants")
 }
 fmt.Println("Descendants of root:")
 for _, d := range descendants {
  fmt.Printf("- %s (%s)\n", d.Name, d.Path)
 }

 // Move Node C under Node B
 err = treeQuery.MoveNode(nodeC.Path, nodeB.Path, tenantID, tenantType)
 if err != nil {
  panic("failed to move Node C")
 }
 movedC, err := treeQuery.GetNodeByCode(nodeC.Code, tenantID, tenantType)
 if err != nil {
  panic("failed to get moved Node C")
 }
 fmt.Printf("Node C moved to: %s\n", movedC.Path)

 // List children of Node B
 children, err := treeQuery.GetChildrenByCode(nodeB.Code, tenantID, tenantType)
 if err != nil {
  panic("failed to get children")
 }
 fmt.Println("Children of Node B:")
 for _, c := range children {
  fmt.Printf("- %s (%s)\n", c.Name, c.Path)
 }
}
Expected Output
Root: Root (/)
Node A: Node A (abc123)
Node B: Node B (def456)
Node C: Node C (abc123/ghi789)
Descendants of root:
- Node A (abc123)
- Node B (def456)
- Node C (abc123/ghi789)
Node C moved to: def456/ghi789
Children of Node B:
- Node C (def456/ghi789)

(Note: Actual ULIDs will differ with each run.)

Contributing

Contributions are welcome! Please submit issues or pull requests to the GitHub repository. Ensure tests are included with any new features or bug fixes.

License

This library is released under the MIT License. See the LICENSE file for details.

Documentation

Overview

Package materialized provides utilities for working with materialized paths in tree structures. Materialized paths are a technique for representing hierarchical data in relational databases that optimizes read operations.

Index

Constants

View Source
const (
	// PathSeparator is the character used to separate node IDs in a path
	PathSeparator = "/"

	// RootPath represents the path of a root node
	RootPath = Path(PathSeparator)
)
View Source
const (
	CondID      = "id = ?"
	CondPathCol = "%s = ?"
)

Variables

View Source
var (
	// ErrInvalidPath is returned when an invalid path is provided
	ErrInvalidPath = errors.New("invalid materialized path")

	// ErrInvalidNodeID is returned when an invalid node ID is provided
	ErrInvalidNodeID = errors.New("invalid node ID")
)
View Source
var (
	// ErrUnauthorized is returned when a tenant tries to access unauthorized data
	ErrUnauthorized = errors.New("unauthorized access")

	// ErrInvalidTableConfig is returned when table configuration is invalid
	ErrInvalidTableConfig = errors.New("invalid table configuration")
)

Functions

func IsValidNodeID

func IsValidNodeID(nid *NodeID) bool

func Validate

func Validate(nid NodeID) error

func ValidateNil

func ValidateNil(nid *NodeID) error

func ValidatePath

func ValidatePath(path string) error

ValidatePath checks if a path is valid

Types

type Code

type Code = NodeID

type NodeID

type NodeID string

NodeID represents a unique identifier for a node in the tree

func NewNodeID

func NewNodeID() NodeID

NewNodeID generates a new ULID-based NodeID

func (NodeID) Validate

func (nid NodeID) Validate() error

Validate checks if the NodeID is a valid ULID

type NodeIDs

type NodeIDs []NodeID

func (NodeIDs) ToPath

func (nids NodeIDs) ToPath() Path

ToPath converts NodeIIDs to a materialized path

type OwnerFields

type OwnerFields struct {
	// Polymorphic owner association
	ID   string `json:"id,omitempty" gorm:"column:owner_id;index:idx_owner"`
	Type string `json:"type,omitempty" gorm:"column:owner_type;index:idx_owner"`
}

type Path

type Path string

Path represents a materialized path in the tree

func NewPath

func NewPath(path string) Path

NewPath creates a new materialized path

func (Path) AppendNode

func (p Path) AppendNode(nodeID NodeID) (Path, error)

AppendNode creates a new path by appending a node ID to the current path

func (Path) Contains

func (p Path) Contains(sub Path) bool

Contains checks if the current path contains another path. This is used to determine if a node is an ancestor of another node.

For example: - path "a/b" contains "a/b/c" (true) - path "a/b" contains "a/b" (false, not a descendant) - path "a/b" contains "a/c" (false, different branch) - root "/" contains "a/b" (true, root contains all) - path "a/b" contains "/" (false, cannot contain root)

The function handles three cases: 1. If current path is root - contains all non-root paths 2. If sub path is root - nothing can contain root 3. Otherwise checks if sub path starts with current path + separator

func (Path) Depth

func (p Path) Depth() int

Depth returns the depth of the node in the tree Root nodes have a depth of 0

func (Path) GetAncestorAtDepth

func (p Path) GetAncestorAtDepth(depth int) (Path, error)

GetAncestorAtDepth returns the ancestor path at the specified depth

func (Path) GetLastNodeID

func (p Path) GetLastNodeID() (NodeID, error)

GetLastNodeID returns the ID of the last node in the path

func (Path) GetNodeIDs

func (p Path) GetNodeIDs() NodeIDs

GetNodeIDs returns a slice of NodeIDs extracted from the path. For a root path, it returns an empty slice. For non-root paths, it splits the path and converts each segment into a NodeID. GetNodeIDs returns all node IDs in the path

func (Path) GetPathPrefix

func (p Path) GetPathPrefix() string

GetPathPrefix returns a SQL LIKE pattern for finding all descendants of this path

func (Path) IsDescendantOf

func (p Path) IsDescendantOf(ancestor Path) bool

IsDescendantOf checks if the current path is a descendant of another path

func (Path) IsDirectParentOf

func (p Path) IsDirectParentOf(child Path) bool

IsDirectParentOf checks if the current path is the direct parent of another path

func (Path) IsRoot

func (p Path) IsRoot() bool

IsRoot checks if the path represents a root node

func (Path) Parent

func (p Path) Parent() (Path, error)

Parent returns the path of the parent node

type TableConfig

type TableConfig struct {
	// TableName is the name of the table in the database
	TableName string
}

TableConfig holds configuration for the tree table

func DefaultTableConfig

func DefaultTableConfig() TableConfig

DefaultTableConfig returns the default table configuration

type TenantFields

type TenantFields struct {
	// Multi-tenancy fields
	ID   string `json:"id,omitempty" gorm:"column:tenant_id;index:idx_tenant"`
	Type string `json:"type,omitempty" gorm:"column:tenant_type;index:idx_tenant"`
}

type TreeNode

type TreeNode struct {
	gorm.Model

	// Code is a unique node identifier
	Code Code `json:"code,omitempty" gorm:"column:code;uniqueIndex:idx_code,sort:asc"`

	// Tenancy fields
	Tenant TenantFields `json:"tenant_fields,omitempty" gorm:"embedded"`

	// Parent-child relationship
	ParentID *Code       `json:"parent_id,omitempty" gorm:"column:parent_id;size:26;index:idx_parent_id;default:null"`
	Parent   *TreeNode   `json:"parent,omitempty" gorm:"foreignKey:ParentID;references:Code"`
	Children []*TreeNode `json:"children,omitempty" gorm:"foreignKey:ParentID;references:Code"`

	Path Path   `json:"path,omitempty" gorm:"column:path;index:idx_path"`
	Name string `json:"name,omitempty" gorm:"column:name"`

	// Owner fields
	Owner OwnerFields `json:"owner_fields,omitempty" gorm:"embedded"`
}

TreeNode represents a node in the materialized path tree

type TreeQuery

type TreeQuery struct {
	// contains filtered or unexported fields
}

TreeQuery provides methods for querying the tree structure

func NewTreeQuery

func NewTreeQuery(db *gorm.DB, config TableConfig) (*TreeQuery, error)

NewTreeQuery creates a new TreeQuery instance

func (*TreeQuery) BatchCreateNodes

func (tq *TreeQuery) BatchCreateNodes(
	nodes []struct {
		Name       string
		ParentPath Path
		OwnerID    string
		OwnerType  string
	},
	tenantID,
	tenantType string,
) ([]*TreeNode, error)

BatchCreateNodes creates multiple nodes in a single transaction

func (*TreeQuery) CreateNode

func (tq *TreeQuery) CreateNode(
	name string,
	parentPath Path,
	tenantID,
	tenantType string,
	ownerID,
	ownerType string,
) (node *TreeNode, err error)

CreateNode creates a new node in the tree

func (*TreeQuery) CreateNodeQuery

func (tq *TreeQuery) CreateNodeQuery(
	tx *gorm.DB,
	name string,
	parentPath Path,
	tenantID,
	tenantType string,
	ownerID,
	ownerType string,
) (*TreeNode, *gorm.DB, error)

CreateNodeQuery creates a new node query in the tree

func (*TreeQuery) DeleteNode

func (tq *TreeQuery) DeleteNode(
	nodePath Path,
	tenantID,
	tenantType string,
	deleteDescendants bool,
) error

DeleteNode deletes a node and optionally its descendants

func (*TreeQuery) GetAncestors

func (tq *TreeQuery) GetAncestors(nodePath Path, tenantID, tenantType string) ([]*TreeNode, error)

GetAncestors retrieves all ancestors of a node

func (*TreeQuery) GetAncestorsNested

func (tq *TreeQuery) GetAncestorsNested(nodePath Path, tenantID, tenantType string) (*TreeNode, error)

GetAncestorsNested retrieves all ancestors of a node in a nested structure

func (*TreeQuery) GetAncestorsQuery

func (tq *TreeQuery) GetAncestorsQuery(tx *gorm.DB, nodePath Path, tenantID, tenantType string) *gorm.DB

GetAncestorsQuery returns a query builder for retrieving all ancestors of a node

func (*TreeQuery) GetChildrenByCode

func (tq *TreeQuery) GetChildrenByCode(code Code, tenantID, tenantType string) ([]*TreeNode, error)

GetChildrenByCode retrieves all direct children of a node by its code

func (*TreeQuery) GetChildrenByCodeQuery

func (tq *TreeQuery) GetChildrenByCodeQuery(tx *gorm.DB, code Code, tenantID, tenantType string) *gorm.DB

func (*TreeQuery) GetChildrenByParentID

func (tq *TreeQuery) GetChildrenByParentID(code *Code, tenantID, tenantType string) ([]*TreeNode, error)

GetChildrenByParentID retrieves all direct children of a node

func (*TreeQuery) GetChildrenByParentIDQuery

func (tq *TreeQuery) GetChildrenByParentIDQuery(tx *gorm.DB, code *Code, tenantID, tenantType string) *gorm.DB

func (*TreeQuery) GetChildrenByPath

func (tq *TreeQuery) GetChildrenByPath(parentPath Path, tenantID, tenantType string) ([]*TreeNode, error)

GetChildrenByPath retrieves all direct children of a node by its path This is an alternative method that uses the path when node ID is not available

func (*TreeQuery) GetChildrenByPathQuery

func (tq *TreeQuery) GetChildrenByPathQuery(tx *gorm.DB, parentPath Path, tenantID, tenantType string) *gorm.DB

GetChildrenByPathQuery returns a query builder for retrieving all direct children of a node by its path

func (*TreeQuery) GetDescendants

func (tq *TreeQuery) GetDescendants(parentPath Path, tenantID, tenantType string) ([]*TreeNode, error)

GetDescendants retrieves all descendants of a node

func (*TreeQuery) GetDescendantsQuery

func (tq *TreeQuery) GetDescendantsQuery(tx *gorm.DB, parentPath Path, tenantID, tenantType string) *gorm.DB

GetDescendantsQuery returns a query builder for retrieving all descendants of a node

func (*TreeQuery) GetNodeByCode

func (tq *TreeQuery) GetNodeByCode(code Code, tenantID, tenantType string) (*TreeNode, error)

GetNodeByCode retrieves a node by its code with tenant security

func (*TreeQuery) GetNodeByCodeQuery

func (tq *TreeQuery) GetNodeByCodeQuery(tx *gorm.DB, code Code, tenantID, tenantType string) *gorm.DB

func (*TreeQuery) GetNodeByID

func (tq *TreeQuery) GetNodeByID(id any, tenantID, tenantType string) (*TreeNode, error)

GetNodeByID retrieves a node by its ID with tenant security

func (*TreeQuery) GetNodeByIDQuery

func (tq *TreeQuery) GetNodeByIDQuery(tx *gorm.DB, id any, tenantID, tenantType string) *gorm.DB

func (*TreeQuery) GetNodeByPath

func (tq *TreeQuery) GetNodeByPath(path Path, tenantID, tenantType string) (*TreeNode, error)

GetNodeByPath retrieves a node by its path with tenant security

func (*TreeQuery) GetNodeByPathQuery

func (tq *TreeQuery) GetNodeByPathQuery(tx *gorm.DB, path Path, tenantID, tenantType string) *gorm.DB

func (*TreeQuery) GetNodeWithChildrenByCode

func (tq *TreeQuery) GetNodeWithChildrenByCode(
	code Code,
	tenantID,
	tenantType string,
	limit int,
	offset int,
) (node *TreeNode, count int64, err error)

GetNodeWithChildrenByCode retrieves a node with its direct children preloaded using the node code with pagination support for the children

func (*TreeQuery) GetNodeWithChildrenByCodeQuery

func (tq *TreeQuery) GetNodeWithChildrenByCodeQuery(
	tx *gorm.DB,
	tenantID,
	tenantType string,
	code Code,
	limit,
	offset int,
) (*gorm.DB, *TreeNode, int64, error)

GetNodeWithChildrenByCodeQuery returns a query builder for retrieving a node with its direct children by code

func (*TreeQuery) GetNodeWithChildrenByPath

func (tq *TreeQuery) GetNodeWithChildrenByPath(
	path Path,
	tenantID,
	tenantType string,
	limit int,
	offset int,
) (*TreeNode, int64, error)

GetNodeWithChildrenByPath retrieves a node with its direct children preloaded using the node path with pagination support for the children

func (*TreeQuery) GetNodeWithChildrenByPathQuery

func (tq *TreeQuery) GetNodeWithChildrenByPathQuery(
	tx *gorm.DB,
	tenantID,
	tenantType string,
	path Path,
	limit,
	offset int,
) (*gorm.DB, *TreeNode, int64, error)

GetNodeWithChildrenByPathQuery returns a query builder for retrieving a node with its direct children by path

func (*TreeQuery) GetNodesByDepth

func (tq *TreeQuery) GetNodesByDepth(
	depth int,
	tenantID,
	tenantType string,
) ([]*TreeNode, error)

GetNodesByDepth retrieves nodes at a specific depth in the tree

func (*TreeQuery) GetNodesByDepthQuery

func (tq *TreeQuery) GetNodesByDepthQuery(
	tx *gorm.DB,
	depth int,
	tenantID,
	tenantType string,
) *gorm.DB

GetNodesByDepthQuery returns a query builder for nodes at a specific depth in the tree

func (*TreeQuery) GetNodesByOwner

func (tq *TreeQuery) GetNodesByOwner(
	ownerID,
	ownerType,
	tenantID,
	tenantType string,
	limit int,
	offset int,
) ([]*TreeNode, int64, error)

GetNodesByOwner retrieves nodes associated with a specific owner

func (*TreeQuery) GetNodesByOwnerQuery

func (tq *TreeQuery) GetNodesByOwnerQuery(
	ownerID,
	ownerType,
	tenantID,
	tenantType string,
) *gorm.DB

GetNodesByOwnerQuery returns a query builder for nodes associated with a specific owner

func (*TreeQuery) GetParentByCode

func (tq *TreeQuery) GetParentByCode(code Code, tenantID, tenantType string) (*TreeNode, error)

GetParentByCode retrieves the parent of a node by its code

func (*TreeQuery) GetParentByCodeQuery

func (tq *TreeQuery) GetParentByCodeQuery(tx *gorm.DB, code Code, tenantID, tenantType string) *gorm.DB

func (*TreeQuery) GetParentByID

func (tq *TreeQuery) GetParentByID(id any, tenantID, tenantType string) (*TreeNode, error)

GetParentByID retrieves the parent of a node

func (*TreeQuery) GetParentByIDQuery

func (tq *TreeQuery) GetParentByIDQuery(tx *gorm.DB, id any, tenantID, tenantType string) *gorm.DB

func (*TreeQuery) GetParentByNode

func (tq *TreeQuery) GetParentByNode(node *TreeNode, tenantID, tenantType string) (*TreeNode, error)

func (*TreeQuery) GetParentByNodeQuery

func (tq *TreeQuery) GetParentByNodeQuery(tx *gorm.DB, node *TreeNode, tenantID, tenantType string) *gorm.DB

func (*TreeQuery) GetParentByPath

func (tq *TreeQuery) GetParentByPath(nodePath Path, tenantID, tenantType string) (*TreeNode, error)

GetParentByPath retrieves the parent of a node by its path

func (*TreeQuery) GetParentByPathQuery

func (tq *TreeQuery) GetParentByPathQuery(tx *gorm.DB, nodePath Path, tenantID, tenantType string) *gorm.DB

func (*TreeQuery) GetRootNode

func (tq *TreeQuery) GetRootNode(tenantID, tenantType string) (*TreeNode, error)

GetRootNode retrieves the root node for a tenant

func (*TreeQuery) GetRootNodeQuery

func (tq *TreeQuery) GetRootNodeQuery(
	tx *gorm.DB,
	tenantID,
	tenantType string,
) *gorm.DB

GetRootNodeQuery returns a query builder for the root node

func (*TreeQuery) Migrate

func (tq *TreeQuery) Migrate(m any) error

func (*TreeQuery) MigrateDefault

func (tq *TreeQuery) MigrateDefault() error

MigrateDefault creates the database schema for the tree table

func (*TreeQuery) MoveNode

func (tq *TreeQuery) MoveNode(
	nodePath Path,
	newParentPath Path,
	tenantID,
	tenantType string,
) error

MoveNode moves a node and all its descendants to a new parent

func (*TreeQuery) SearchNodes

func (tq *TreeQuery) SearchNodes(
	query string,
	tenantID,
	tenantType string,
	limit int,
	offset int,
) ([]*TreeNode, int64, error)

SearchNodes searches for nodes by name or metadata with tenant security

func (*TreeQuery) UpdateNode

func (tq *TreeQuery) UpdateNode(
	code Code,
	tenantID,
	tenantType string,
	updates map[string]interface{},
) error

UpdateNode updates a node's properties

func (*TreeQuery) UpdateNodeQuery

func (tq *TreeQuery) UpdateNodeQuery(
	tx *gorm.DB,
	code Code,
	tenantID,
	tenantType string,
	updates map[string]interface{},
) (*gorm.DB, error)

UpdateNodeQuery prepares the query for updating a node

func (*TreeQuery) WithTransaction

func (tq *TreeQuery) WithTransaction(tx *gorm.DB) *TreeQuery

WithTransaction allows executing operations within an existing transaction

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL