query

package
v0.0.0-...-295a8b0 Latest Latest
Warning

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

Go to latest
Published: Jan 7, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package query provides a fluent, builder-style API for querying GEDCOM genealogical data.

The query package builds on top of a graph representation of GEDCOM data, enabling efficient traversal, path finding, relationship calculation, and complex filtering.

Quick Start

package main

import (
	"fmt"
	"github.com/lesfleursdelanuitdev/ligneous-gedcom/types"
	"github.com/lesfleursdelanuitdev/ligneous-gedcom/parser"
	"github.com/lesfleursdelanuitdev/ligneous-gedcom/query"
)

func main() {
	// Parse GEDCOM file
	p := parser.NewHierarchicalParser()
	tree, err := p.Parse("family.ged")
	if err != nil {
		panic(err)
	}

	// Create query builder
	q, err := query.NewQuery(tree)
	if err != nil {
		panic(err)
	}

	// Find all ancestors
	ancestors, _ := q.Individual("@I1@").Ancestors().Execute()
	for _, ancestor := range ancestors {
		fmt.Printf("Ancestor: %s\n", ancestor.GetName())
	}
}

Query Types

## IndividualQuery

Query operations starting from a specific individual:

// Direct relationships
parents, _ := q.Individual("@I1@").Parents()
children, _ := q.Individual("@I1@").Children()
siblings, _ := q.Individual("@I1@").Siblings()
spouses, _ := q.Individual("@I1@").Spouses()

// Extended relationships
grandparents, _ := q.Individual("@I1@").Grandparents()
uncles, _ := q.Individual("@I1@").Uncles()
cousins, _ := q.Individual("@I1@").Cousins(1) // 1st cousins

// Complex queries
ancestors, _ := q.Individual("@I1@").Ancestors().MaxGenerations(5).Execute()
descendants, _ := q.Individual("@I1@").Descendants().IncludeSelf().Execute()

## AncestorQuery

Configurable ancestor search with options:

ancestors, _ := q.Individual("@I1@").
	Ancestors().
	MaxGenerations(3).        // Limit to 3 generations
	IncludeSelf().            // Include starting individual
	Filter(func(indi *types.IndividualRecord) bool {
		return indi.GetSex() == "M"  // Only males
	}).
	Execute()

count, _ := q.Individual("@I1@").Ancestors().Count()
exists, _ := q.Individual("@I1@").Ancestors().Exists()

## DescendantQuery

Configurable descendant search (same API as AncestorQuery):

descendants, _ := q.Individual("@I1@").
	Descendants().
	MaxGenerations(2).
	Execute()

## RelationshipQuery

Calculate relationship between two individuals:

result, _ := q.Individual("@I1@").RelationshipTo("@I2@").Execute()

fmt.Printf("Relationship: %s\n", result.RelationshipType)
fmt.Printf("Degree: %d\n", result.Degree)        // For cousins: 1st, 2nd, etc.
fmt.Printf("Removal: %d\n", result.Removal)      // For removed cousins
fmt.Printf("Is Direct: %v\n", result.IsDirect)
fmt.Printf("Is Collateral: %v\n", result.IsCollateral)

## PathQuery

Find paths between two individuals:

// Shortest path
path, _ := q.Individual("@I1@").PathTo("@I2@").Shortest()
fmt.Printf("Path length: %d\n", path.Length)

// All paths
paths, _ := q.Individual("@I1@").
	PathTo("@I2@").
	MaxLength(10).
	IncludeBlood(true).
	IncludeMarital(false).
	All()

## FilterQuery

Filter individuals by various criteria:

// Filter by name
results, _ := q.Filter().ByName("John").Execute()

// Filter by multiple criteria (AND logic)
results, _ := q.Filter().
	ByName("John").
	BySex("M").
	HasChildren().
	Execute()

// Filter by date range
start := time.Date(1800, 1, 1, 0, 0, 0, 0, time.UTC)
end := time.Date(1900, 12, 31, 23, 59, 59, 0, time.UTC)
results, _ := q.Filter().
	ByBirthDate(start, end).
	ByBirthPlace("New York").
	Execute()

// Count matching individuals
count, _ := q.Filter().Living().HasSpouse().Count()

## FamilyQuery

Query operations starting from a family:

husband, _ := q.Family("@F1@").Husband()
wife, _ := q.Family("@F1@").Wife()
children, _ := q.Family("@F1@").Children()
parents, _ := q.Family("@F1@").Parents()  // Husband and wife

marriageDate, _ := q.Family("@F1@").MarriageDate()
events, _ := q.Family("@F1@").Events()

## MultiIndividualQuery

Query operations on multiple individuals:

// Find ancestors of all individuals (union)
ancestors, _ := q.Individuals("@I1@", "@I2@", "@I3@").Ancestors()

// Find common ancestors
common, _ := q.Individuals("@I1@", "@I2@").CommonAncestors()

// Union of results
results, _ := q.Individuals("@I1@", "@I2@").
	Union(
		func(iq *query.IndividualQuery) ([]*types.IndividualRecord, error) {
			return iq.Parents()
		},
		func(iq *query.IndividualQuery) ([]*types.IndividualRecord, error) {
			return iq.Siblings()
		},
	)

## GraphMetricsQuery

Graph analytics and metrics:

metrics := q.Metrics()

// Node metrics
degree, _ := metrics.Degree("@I1@")
inDegree, _ := metrics.InDegree("@I1@")
outDegree, _ := metrics.OutDegree("@I1@")

// Graph metrics
diameter, _ := metrics.Diameter()
avgPathLength, _ := metrics.AveragePathLength()
avgDegree, _ := metrics.AverageDegree()
density, _ := metrics.Density()

// Centrality measures
centrality, _ := metrics.Centrality(query.CentralityDegree)
betweenness, _ := metrics.Centrality(query.CentralityBetweenness)
closeness, _ := metrics.Centrality(query.CentralityCloseness)

// Connectivity
connected, _ := metrics.IsConnected("@I1@", "@I2@")
components, _ := metrics.ConnectedComponents()

// Longest path
longestPath, _ := metrics.LongestPath()

Graph Algorithms

The package also provides direct access to graph algorithms:

graph := q.Graph()

// Traversal
graph.BFS("@I1@", func(node GraphNode) bool {
	fmt.Printf("Visited: %s\n", node.ID())
	return true  // Continue
})

// Path finding
path, _ := graph.ShortestPath("@I1@", "@I2@")
allPaths, _ := graph.AllPaths("@I1@", "@I2@", 10)

// Ancestors
common, _ := graph.CommonAncestors("@I1@", "@I2@")
lca, _ := graph.LowestCommonAncestor("@I1@", "@I2@")

// Relationships
result, _ := graph.CalculateRelationship("@I1@", "@I2@")

Performance

The query package is designed for performance:

  • Graph is built once and reused for multiple queries
  • Cached relationships (parents, children, spouses) for O(1) access
  • Efficient algorithms (BFS for shortest path, DFS for all paths)
  • Thread-safe operations

Thread Safety

All query operations are thread-safe and can be called concurrently. The underlying graph uses RWMutex for concurrent read access.

Examples

## Example 1: Find All Ancestors

ancestors, _ := q.Individual("@I1@").
	Ancestors().
	MaxGenerations(5).
	Execute()

for _, ancestor := range ancestors {
	fmt.Printf("Ancestor: %s\n", ancestor.GetName())
}

## Example 2: Find Relationship

result, _ := q.Individual("@I1@").RelationshipTo("@I2@").Execute()
fmt.Printf("Relationship: %s\n", result.RelationshipType)
fmt.Printf("Degree: %d\n", result.Degree)

## Example 3: Find All Cousins

cousins, _ := q.Individual("@I1@").Cousins(1)  // 1st cousins
for _, cousin := range cousins {
	fmt.Printf("Cousin: %s\n", cousin.GetName())
}

## Example 4: Find Path Between Two Individuals

paths, _ := q.Individual("@I1@").PathTo("@I2@").All()
for _, path := range paths {
	fmt.Printf("Path length: %d\n", path.Length)
	for _, node := range path.Nodes {
		if indi, ok := node.(*query.IndividualNode); ok {
			fmt.Printf("  -> %s\n", indi.Individual.GetName())
		}
	}
}

## Example 5: Complex Filtering

results, _ := q.Filter().
	ByName("John").
	BySex("M").
	ByBirthDate(
		time.Date(1800, 1, 1, 0, 0, 0, 0, time.UTC),
		time.Date(1900, 12, 31, 23, 59, 59, 0, time.UTC),
	).
	HasChildren().
	Execute()

## Example 6: Graph Metrics

metrics := q.Metrics()

// Find most connected individual
centrality, _ := metrics.Centrality(query.CentralityDegree)
maxDegree := 0.0
mostConnected := ""
for id, degree := range centrality {
	if degree > maxDegree {
		maxDegree = degree
		mostConnected = id
	}
}
fmt.Printf("Most connected: %s (degree: %.0f)\n", mostConnected, maxDegree)

// Check graph connectivity
components, _ := metrics.ConnectedComponents()
fmt.Printf("Number of connected components: %d\n", len(components))

Index

Constants

View Source
const TestTimeout = 2 * time.Minute

TestTimeout is the maximum duration for a test (2 minutes) This constant is used by testWithTimeout in hybrid_stress_test.go

Variables

This section is empty.

Functions

func AddTestFamily

func AddTestFamily(tree *types.GedcomTree, xref string, husband, wife string, children []string) *types.FamilyRecord

AddTestFamily adds a family to a tree and returns it.

func AddTestIndividual

func AddTestIndividual(tree *types.GedcomTree, xref, name string) *types.IndividualRecord

AddTestIndividual adds an individual to a tree and returns it.

func CreateTestFamily

func CreateTestFamily(xref string, husband, wife string, children []string) *types.FamilyRecord

CreateTestFamily creates a test family record.

func CreateTestFamilyWithMarriage

func CreateTestFamilyWithMarriage(xref, husband, wife string, marriageDate, marriagePlace string) *types.FamilyRecord

CreateTestFamilyWithMarriage creates a test family with marriage information.

func CreateTestIndividual

func CreateTestIndividual(xref, name string) *types.IndividualRecord

CreateTestIndividual creates a test individual record with the given XREF and name.

func CreateTestIndividualWithBirth

func CreateTestIndividualWithBirth(xref, name, birthDate, birthPlace string) *types.IndividualRecord

CreateTestIndividualWithBirth creates a test individual with birth information.

func CreateTestIndividualWithName

func CreateTestIndividualWithName(xref, name string) *types.IndividualRecord

CreateTestIndividualWithName creates a test individual with a structured name.

func CreateTestTree

func CreateTestTree() *types.GedcomTree

CreateTestTree creates a new empty GEDCOM tree for testing.

func DeserializeComponents

func DeserializeComponents(data []byte) ([]uint32, error)

DeserializeComponents deserializes component data from bytes

func ForEachFamily

func ForEachFamily(graph *Graph, fn func(*FamilyNode) error) error

ForEachFamily iterates over all families in the graph, calling fn for each. Stops iteration if fn returns an error.

func ForEachIndividual

func ForEachIndividual(graph *Graph, fn func(*IndividualNode) error) error

ForEachIndividual iterates over all individuals in the graph, calling fn for each. Stops iteration if fn returns an error.

func SaveConfig

func SaveConfig(config *Config, configPath string) error

SaveConfig saves configuration to file

func SerializeComponents

func SerializeComponents(nodeIDs []uint32) ([]byte, error)

SerializeComponents serializes component data (node IDs) to bytes

func SerializeEdges

func SerializeEdges(edges []*Edge, graph *Graph) ([]byte, error)

SerializeEdges serializes a slice of edges to bytes

func SerializeNode

func SerializeNode(node GraphNode, graph *Graph) ([]byte, error)

SerializeNode serializes a node to bytes for storage in BadgerDB Note: We only store metadata (XREF, type) - the full record is reconstructed from tree For EventNode, we also store EventType and EventData

Types

type AncestorOptions

type AncestorOptions struct {
	MaxGenerations int                                // Limit depth (0 = unlimited)
	IncludeSelf    bool                               // Include starting individual
	Filter         func(*types.IndividualRecord) bool // Custom filter function
	Order          Order                              // BFS or DFS order
}

AncestorOptions holds configuration for ancestor queries.

func NewAncestorOptions

func NewAncestorOptions() *AncestorOptions

NewAncestorOptions creates new AncestorOptions with defaults.

type AncestorPath

type AncestorPath struct {
	Ancestor *types.IndividualRecord
	Path     *Path
	Depth    int
}

AncestorPath represents an ancestor with path information.

type AncestorQuery

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

AncestorQuery represents a query for ancestors.

func (*AncestorQuery) Count

func (aq *AncestorQuery) Count() (int, error)

Count returns the number of ancestors.

func (*AncestorQuery) Execute

func (aq *AncestorQuery) Execute() ([]*types.IndividualRecord, error)

Execute runs the query and returns ancestor records.

func (*AncestorQuery) ExecuteWithPaths

func (aq *AncestorQuery) ExecuteWithPaths() ([]*AncestorPath, error)

ExecuteWithPaths returns ancestors with path information.

func (*AncestorQuery) Exists

func (aq *AncestorQuery) Exists() (bool, error)

Exists checks if any ancestors exist.

func (*AncestorQuery) Filter

func (aq *AncestorQuery) Filter(fn func(*types.IndividualRecord) bool) *AncestorQuery

Filter applies a custom filter function to results.

func (*AncestorQuery) IncludeSelf

func (aq *AncestorQuery) IncludeSelf() *AncestorQuery

IncludeSelf includes the starting individual in results.

func (*AncestorQuery) MaxGenerations

func (aq *AncestorQuery) MaxGenerations(n int) *AncestorQuery

MaxGenerations limits the depth of the ancestor search.

type BadgerDBStorage

type BadgerDBStorage interface {
	BadgerDB() *badger.DB
}

BadgerDBStorage is an interface for storage types that have BadgerDB

type BaseNode

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

BaseNode provides common functionality for all graph nodes.

func (*BaseNode) AddInEdge

func (bn *BaseNode) AddInEdge(edge *Edge)

AddInEdge adds an incoming edge.

func (*BaseNode) AddOutEdge

func (bn *BaseNode) AddOutEdge(edge *Edge)

AddOutEdge adds an outgoing edge.

func (*BaseNode) Degree

func (bn *BaseNode) Degree() int

Degree returns the total number of edges.

func (*BaseNode) ID

func (bn *BaseNode) ID() string

ID returns the unique identifier of the node.

func (*BaseNode) InDegree

func (bn *BaseNode) InDegree() int

InDegree returns the number of incoming edges.

func (*BaseNode) InEdges

func (bn *BaseNode) InEdges() []*Edge

InEdges returns all incoming edges.

func (*BaseNode) Neighbors

func (bn *BaseNode) Neighbors() []GraphNode

Neighbors returns all nodes connected to this node.

func (*BaseNode) NodeType

func (bn *BaseNode) NodeType() NodeType

NodeType returns the type of the node.

func (*BaseNode) OutDegree

func (bn *BaseNode) OutDegree() int

OutDegree returns the number of outgoing edges.

func (*BaseNode) OutEdges

func (bn *BaseNode) OutEdges() []*Edge

OutEdges returns all outgoing edges. If lazy mode is enabled, triggers edge loading if not already loaded.

func (*BaseNode) Record

func (bn *BaseNode) Record() types.Record

Record returns the original GEDCOM record.

func (*BaseNode) RemoveInEdge

func (bn *BaseNode) RemoveInEdge(edge *Edge)

RemoveInEdge removes an incoming edge.

func (*BaseNode) RemoveOutEdge

func (bn *BaseNode) RemoveOutEdge(edge *Edge)

RemoveOutEdge removes an outgoing edge.

type CacheConfig

type CacheConfig struct {
	// Hybrid cache sizes
	HybridNodeCacheSize  int `json:"hybrid_node_cache_size"`  // Default: 50000
	HybridXrefCacheSize  int `json:"hybrid_xref_cache_size"`  // Default: 25000
	HybridQueryCacheSize int `json:"hybrid_query_cache_size"` // Default: 5000

	// Query cache size (for in-memory graph)
	QueryCacheSize int `json:"query_cache_size"` // Default: 1000
}

CacheConfig holds cache size configurations

type CacheStats

type CacheStats struct {
	NodeCacheSize      int
	NodeCacheCapacity  int
	XrefCacheSize      int
	XrefCacheCapacity  int
	QueryCacheSize     int
	QueryCacheCapacity int
}

CacheStats provides statistics about cache usage

type CentralityMetric

type CentralityMetric string

CentralityMetric represents the type of centrality measure.

const (
	CentralityDegree      CentralityMetric = "degree"      // Number of connections
	CentralityBetweenness CentralityMetric = "betweenness" // Betweenness centrality
	CentralityCloseness   CentralityMetric = "closeness"   // Closeness centrality
)

type ComponentOptions

type ComponentOptions struct {
	MaxDepth int // Limit traversal depth (0 = unlimited)
	MaxSize  int // Limit result size (0 = unlimited)
}

ComponentOptions holds configuration for component queries.

func NewComponentOptions

func NewComponentOptions() *ComponentOptions

NewComponentOptions creates new ComponentOptions with defaults.

type Config

type Config struct {
	// Cache configuration
	Cache CacheConfig `json:"cache"`

	// Timeout configuration
	Timeout TimeoutConfig `json:"timeout"`

	// Database configuration
	Database DatabaseConfig `json:"database"`
}

Config represents the configuration for query operations

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a configuration with default values

func LoadConfig

func LoadConfig(configPath string) (*Config, error)

LoadConfig loads configuration from file or returns default It searches for config files in the following order: 1. The provided configPath (if not empty) 2. ./gedcom-query-config.json (current directory) 3. ~/.gedcom/query-config.json (user home) 4. ~/.config/gedcom/query-config.json (XDG config)

type DatabaseConfig

type DatabaseConfig struct {
	// SQLite configuration
	SQLiteMaxOpenConns int `json:"sqlite_max_open_conns"` // Default: 10
	SQLiteMaxIdleConns int `json:"sqlite_max_idle_conns"` // Default: 5

	// PostgreSQL configuration
	PostgreSQLMaxOpenConns    int           `json:"postgresql_max_open_conns"`     // Default: 25
	PostgreSQLMaxIdleConns    int           `json:"postgresql_max_idle_conns"`     // Default: 10
	PostgreSQLConnMaxLifetime time.Duration `json:"postgresql_conn_max_lifetime"`  // Default: 5m
	PostgreSQLConnMaxIdleTime time.Duration `json:"postgresql_conn_max_idle_time"` // Default: 1m
	PostgreSQLDatabaseURL     string        `json:"postgresql_database_url"`       // Default: from DATABASE_URL env var

	// BadgerDB configuration
	BadgerDBValueLogFileSize int64 `json:"badgerdb_value_log_file_size"` // Default: 1GB
}

DatabaseConfig holds database-specific configurations

type DescendantOptions

type DescendantOptions struct {
	MaxGenerations int                                // Limit depth (0 = unlimited)
	IncludeSelf    bool                               // Include starting individual
	Filter         func(*types.IndividualRecord) bool // Custom filter function
	Order          Order                              // BFS or DFS order
}

DescendantOptions holds configuration for descendant queries.

func NewDescendantOptions

func NewDescendantOptions() *DescendantOptions

NewDescendantOptions creates new DescendantOptions with defaults.

type DescendantQuery

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

DescendantQuery represents a query for descendants.

func (*DescendantQuery) Count

func (dq *DescendantQuery) Count() (int, error)

Count returns the number of descendants.

func (*DescendantQuery) Execute

func (dq *DescendantQuery) Execute() ([]*types.IndividualRecord, error)

Execute runs the query and returns descendant records.

func (*DescendantQuery) Exists

func (dq *DescendantQuery) Exists() (bool, error)

Exists checks if any descendants exist.

func (*DescendantQuery) Filter

Filter applies a custom filter function to results.

func (*DescendantQuery) IncludeSelf

func (dq *DescendantQuery) IncludeSelf() *DescendantQuery

IncludeSelf includes the starting individual in results.

func (*DescendantQuery) MaxGenerations

func (dq *DescendantQuery) MaxGenerations(n int) *DescendantQuery

MaxGenerations limits the depth of the descendant search.

type Direction

type Direction string

Direction represents the direction of an edge.

const (
	DirectionForward       Direction = "forward"       // From -> To
	DirectionBackward      Direction = "backward"      // To -> From
	DirectionBidirectional Direction = "bidirectional" // Both directions
)

type Edge

type Edge struct {
	// Core data
	ID   string    // Unique edge ID
	From GraphNode // Source node
	To   GraphNode // Target node

	// Edge properties
	EdgeType  EdgeType    // Type of relationship
	Direction Direction   // Forward, Backward, Bidirectional
	Family    *FamilyNode // Family context (for FAMC/FAMS edges)

	// Metadata
	Properties map[string]interface{} // Additional edge properties
	Weight     float64                // Optional weight for algorithms
}

Edge represents a relationship between two nodes in the graph.

func DeserializeEdges

func DeserializeEdges(data []byte, graph *Graph) ([]*Edge, error)

DeserializeEdges deserializes bytes into a slice of edges

func NewBidirectionalEdge

func NewBidirectionalEdge(id string, from GraphNode, to GraphNode, edgeType EdgeType) *Edge

NewBidirectionalEdge creates a bidirectional edge.

func NewEdge

func NewEdge(id string, from GraphNode, to GraphNode, edgeType EdgeType) *Edge

NewEdge creates a new edge between two nodes.

func NewEdgeWithFamily

func NewEdgeWithFamily(id string, from GraphNode, to GraphNode, edgeType EdgeType, family *FamilyNode) *Edge

NewEdgeWithFamily creates an edge with family context.

func (*Edge) Connects

func (e *Edge) Connects(node GraphNode) bool

Connects returns true if the edge connects the given node.

func (*Edge) IsBidirectional

func (e *Edge) IsBidirectional() bool

IsBidirectional returns true if the edge is bidirectional.

func (*Edge) OtherNode

func (e *Edge) OtherNode(node GraphNode) GraphNode

OtherNode returns the other node in the edge (not the given node).

type EdgeData

type EdgeData struct {
	FromID     uint32
	ToID       uint32
	EdgeType   EdgeType
	FamilyID   uint32 // For FAMC/FAMS edges
	Direction  Direction
	Properties map[string]interface{}
}

EdgeData represents serialized edge data for BadgerDB

type EdgeType

type EdgeType string

EdgeType represents the type of relationship between nodes.

const (
	// Individual <-> Family relationships
	EdgeTypeFAMC EdgeType = "FAMC" // Individual is child of family
	EdgeTypeFAMS EdgeType = "FAMS" // Individual is spouse in family
	EdgeTypeCHIL EdgeType = "CHIL" // Family has child
	EdgeTypeHUSB EdgeType = "HUSB" // Family has husband
	EdgeTypeWIFE EdgeType = "WIFE" // Family has wife

	// Reference relationships
	EdgeTypeNOTE     EdgeType = "NOTE"      // References a note
	EdgeTypeSOUR     EdgeType = "SOUR"      // References a source
	EdgeTypeREPO     EdgeType = "REPO"      // References a repository
	EdgeTypeHasEvent EdgeType = "has_event" // Individual/Family has event

	// Derived/computed edges (for convenience)
	EdgeTypeParent  EdgeType = "parent"  // Computed: parent relationship
	EdgeTypeChild   EdgeType = "child"   // Computed: child relationship
	EdgeTypeSpouse  EdgeType = "spouse"  // Computed: spouse relationship
	EdgeTypeSibling EdgeType = "sibling" // Computed: sibling relationship
)

type EventCollectionQuery

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

EventCollectionQuery provides collection operations on events.

func NewEventCollectionQuery

func NewEventCollectionQuery(graph *Graph) *EventCollectionQuery

NewEventCollectionQuery creates a new EventCollectionQuery.

func (*EventCollectionQuery) All

func (ecq *EventCollectionQuery) All() ([]EventInfo, error)

All returns all events from all individuals and families.

func (*EventCollectionQuery) By

By specifies uniqueness criteria.

func (*EventCollectionQuery) Count

func (ecq *EventCollectionQuery) Count() (int, error)

Count returns the number of events.

func (*EventCollectionQuery) Execute

func (ecq *EventCollectionQuery) Execute() ([]EventInfo, error)

Execute runs the query and returns results with uniqueness applied.

func (*EventCollectionQuery) Filter

Filter adds a filter condition.

func (*EventCollectionQuery) FromFamilies

func (ecq *EventCollectionQuery) FromFamilies() *EventCollectionQuery

FromFamilies only includes events from families.

func (*EventCollectionQuery) FromIndividuals

func (ecq *EventCollectionQuery) FromIndividuals() *EventCollectionQuery

FromIndividuals only includes events from individuals.

func (*EventCollectionQuery) OfType

func (ecq *EventCollectionQuery) OfType(eventType string) *EventCollectionQuery

OfType filters by event type.

func (*EventCollectionQuery) Unique

Unique returns unique events based on criteria.

type EventFilter

type EventFilter func(EventInfo) bool

EventFilter represents a filter function for events.

type EventInfo

type EventInfo struct {
	EventID     string
	EventType   string
	Date        string
	Place       string
	Description string
	Owner       GraphNode // Individual or Family that owns this event
}

EventInfo represents information about an event.

type EventNode

type EventNode struct {
	*BaseNode
	EventID   string
	EventType string
	EventData map[string]interface{}

	// Cached relationships
	Owner   GraphNode
	Sources []*SourceNode
	Notes   []*NoteNode
}

EventNode represents an event embedded within an Individual or Family record.

func NewEventNode

func NewEventNode(eventID string, eventType string, eventData map[string]interface{}) *EventNode

NewEventNode creates a new EventNode.

func (*EventNode) Record

func (en *EventNode) Record() types.Record

Record returns nil for EventNode (events don't have top-level records).

type EventUniqueBy

type EventUniqueBy string

EventUniqueBy specifies what makes an event unique.

const (
	EventUniqueByID        EventUniqueBy = "id"         // By event ID (all unique)
	EventUniqueByType      EventUniqueBy = "type"       // By event type
	EventUniqueByDate      EventUniqueBy = "date"       // By date
	EventUniqueByPlace     EventUniqueBy = "place"      // By place
	EventUniqueByTypeDate  EventUniqueBy = "type_date"  // By type + date
	EventUniqueByTypePlace EventUniqueBy = "type_place" // By type + place
	EventUniqueByOwner     EventUniqueBy = "owner"      // By owner (individual/family)
)

type FamilyCollectionQuery

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

FamilyCollectionQuery provides collection operations on families.

func NewFamilyCollectionQuery

func NewFamilyCollectionQuery(graph *Graph) *FamilyCollectionQuery

NewFamilyCollectionQuery creates a new FamilyCollectionQuery.

func (*FamilyCollectionQuery) All

func (fcq *FamilyCollectionQuery) All() ([]*types.FamilyRecord, error)

All returns all families in the tree.

func (*FamilyCollectionQuery) By

By specifies uniqueness criteria.

func (*FamilyCollectionQuery) Count

func (fcq *FamilyCollectionQuery) Count() (int, error)

Count returns the number of families.

func (*FamilyCollectionQuery) Execute

func (fcq *FamilyCollectionQuery) Execute() ([]*types.FamilyRecord, error)

Execute runs the query and returns results with uniqueness applied.

func (*FamilyCollectionQuery) Filter

Filter adds a filter condition.

func (*FamilyCollectionQuery) Unique

Unique returns unique families based on criteria.

type FamilyFilter

type FamilyFilter func(*types.FamilyRecord) bool

FamilyFilter represents a filter function for families.

type FamilyNode

type FamilyNode struct {
	*BaseNode
	Family *types.FamilyRecord
	// contains filtered or unexported fields
}

FamilyNode represents a family unit (marriage/partnership and children).

func CollectFamilies

func CollectFamilies(graph *Graph, filter func(*FamilyNode) bool) []*FamilyNode

CollectFamilies collects all families matching the filter.

func NewFamilyNode

func NewFamilyNode(xrefID string, record *types.FamilyRecord) *FamilyNode

NewFamilyNode creates a new FamilyNode.

func (*FamilyNode) Children

func (node *FamilyNode) Children() []*IndividualNode

Children returns all children of this family. Computes children from edges (edge-based traversal). This is the recommended way to get relationships - use graph nodes, not records.

func (*FamilyNode) Husband

func (node *FamilyNode) Husband() *IndividualNode

Husband returns the husband of this family. Computes husband from edges (edge-based traversal). This is the recommended way to get relationships - use graph nodes, not records.

func (*FamilyNode) Wife

func (node *FamilyNode) Wife() *IndividualNode

Wife returns the wife of this family. Computes wife from edges (edge-based traversal). This is the recommended way to get relationships - use graph nodes, not records.

type FamilyQuery

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

FamilyQuery represents a query starting from a family.

func (*FamilyQuery) Children

func (fq *FamilyQuery) Children() ([]*types.IndividualRecord, error)

Children returns all children's individual records.

func (*FamilyQuery) DivorceDate

func (fq *FamilyQuery) DivorceDate() (string, error)

DivorceDate returns the divorce date.

func (*FamilyQuery) DivorceDateParsed

func (fq *FamilyQuery) DivorceDateParsed() (*types.GedcomDate, error)

DivorceDateParsed returns the divorce date as a parsed GedcomDate.

func (*FamilyQuery) DivorcePlace

func (fq *FamilyQuery) DivorcePlace() (string, error)

DivorcePlace returns the divorce place.

func (*FamilyQuery) Events

func (fq *FamilyQuery) Events() ([]*EventNode, error)

Events returns all family events (marriage, divorce, etc.).

func (*FamilyQuery) Exists

func (fq *FamilyQuery) Exists() bool

Exists checks if the family exists.

func (*FamilyQuery) GetAllNotes

func (fq *FamilyQuery) GetAllNotes() ([]NoteInfo, error)

GetAllNotesForFamily returns all notes associated with a family, including both referenced notes (via NOTE xrefs) and inline notes (embedded in the record).

func (*FamilyQuery) GetEvents

func (fq *FamilyQuery) GetEvents() ([]EventInfo, error)

GetEventsForFamily returns all events associated with a family.

func (*FamilyQuery) GetRecord

func (fq *FamilyQuery) GetRecord() (*types.FamilyRecord, error)

GetRecord returns the underlying FamilyRecord.

func (*FamilyQuery) Husband

func (fq *FamilyQuery) Husband() (*types.IndividualRecord, error)

Husband returns the husband's individual record.

func (*FamilyQuery) MarriageDate

func (fq *FamilyQuery) MarriageDate() (string, error)

MarriageDate returns the marriage date.

func (*FamilyQuery) MarriageDateParsed

func (fq *FamilyQuery) MarriageDateParsed() (*types.GedcomDate, error)

MarriageDateParsed returns the marriage date as a parsed GedcomDate.

func (*FamilyQuery) MarriagePlace

func (fq *FamilyQuery) MarriagePlace() (string, error)

MarriagePlace returns the marriage place.

func (*FamilyQuery) Parents

func (fq *FamilyQuery) Parents() ([]*types.IndividualRecord, error)

Parents returns the parents (husband and wife) of this family.

func (*FamilyQuery) Wife

func (fq *FamilyQuery) Wife() (*types.IndividualRecord, error)

Wife returns the wife's individual record.

type FamilyUniqueBy

type FamilyUniqueBy string

FamilyUniqueBy specifies what makes a family unique.

const (
	FamilyUniqueByXref          FamilyUniqueBy = "xref"           // By family XREF (all unique)
	FamilyUniqueByHusband       FamilyUniqueBy = "husband"        // By husband XREF
	FamilyUniqueByWife          FamilyUniqueBy = "wife"           // By wife XREF
	FamilyUniqueByChildren      FamilyUniqueBy = "children"       // By number of children
	FamilyUniqueByMarriageDate  FamilyUniqueBy = "marriage_date"  // By marriage date
	FamilyUniqueByMarriagePlace FamilyUniqueBy = "marriage_place" // By marriage place
	FamilyUniqueByHusbandWife   FamilyUniqueBy = "husband_wife"   // By husband+wife combination
)

type Filter

type Filter func(*types.IndividualRecord) bool

Filter represents a filter function for individuals.

type FilterIndexes

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

FilterIndexes contains indexes for fast filtering.

type FilterQuery

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

FilterQuery represents a query with filtering capabilities.

func NewFilterQuery

func NewFilterQuery(graph *Graph) *FilterQuery

NewFilterQuery creates a new FilterQuery.

func (*FilterQuery) ByBirthDate

func (fq *FilterQuery) ByBirthDate(start, end time.Time) *FilterQuery

ByBirthDate filters by birth date range. Uses index for fast lookup.

func (*FilterQuery) ByBirthDateAfter

func (fq *FilterQuery) ByBirthDateAfter(year int) *FilterQuery

ByBirthDateAfter filters individuals born after the specified year.

func (*FilterQuery) ByBirthDateBefore

func (fq *FilterQuery) ByBirthDateBefore(year int) *FilterQuery

ByBirthDateBefore filters individuals born before the specified year.

func (*FilterQuery) ByBirthDateRange

func (fq *FilterQuery) ByBirthDateRange(start, end time.Time) *FilterQuery

ByBirthDateRange filters individuals born within a date range. This is an alias for ByBirthDate for consistency.

func (*FilterQuery) ByBirthDay

func (fq *FilterQuery) ByBirthDay(day int) *FilterQuery

ByBirthDay filters individuals born on a specific day of month (1-31). Note: This checks the day component only, not the month/year.

func (*FilterQuery) ByBirthMonth

func (fq *FilterQuery) ByBirthMonth(month int) *FilterQuery

ByBirthMonth filters individuals born in a specific month (1-12).

func (*FilterQuery) ByBirthMonthAndDay

func (fq *FilterQuery) ByBirthMonthAndDay(month int, day int) *FilterQuery

ByBirthMonthAndDay filters individuals born on a specific month and day.

func (*FilterQuery) ByBirthPlace

func (fq *FilterQuery) ByBirthPlace(place string) *FilterQuery

ByBirthPlace filters by birth place (case-insensitive substring match). Uses index for fast lookup.

func (*FilterQuery) ByBirthYear

func (fq *FilterQuery) ByBirthYear(year int) *FilterQuery

ByBirthYear filters individuals born in the specified year.

func (*FilterQuery) ByGivenName

func (fq *FilterQuery) ByGivenName(givenName string) *FilterQuery

ByGivenName filters individuals by first name (given name). Case-insensitive substring match.

func (*FilterQuery) ByGivenNameExact

func (fq *FilterQuery) ByGivenNameExact(givenName string) *FilterQuery

ByGivenNameExact filters individuals by exact first name match (case-insensitive).

func (*FilterQuery) ByName

func (fq *FilterQuery) ByName(pattern string) *FilterQuery

ByName filters by name (case-insensitive substring match). Uses index for fast lookup.

func (*FilterQuery) ByNameEnds

func (fq *FilterQuery) ByNameEnds(suffix string) *FilterQuery

ByNameEnds filters by name ending with suffix (case-insensitive).

func (*FilterQuery) ByNameExact

func (fq *FilterQuery) ByNameExact(name string) *FilterQuery

ByNameExact filters by exact name match (case-insensitive).

func (*FilterQuery) ByNameStarts

func (fq *FilterQuery) ByNameStarts(prefix string) *FilterQuery

ByNameStarts filters by name starting with prefix (case-insensitive).

func (*FilterQuery) BySex

func (fq *FilterQuery) BySex(sex string) *FilterQuery

BySex filters by sex. Uses index for fast lookup.

func (*FilterQuery) BySurname

func (fq *FilterQuery) BySurname(surname string) *FilterQuery

BySurname filters individuals by last name (surname). Case-insensitive substring match.

func (*FilterQuery) BySurnameExact

func (fq *FilterQuery) BySurnameExact(surname string) *FilterQuery

BySurnameExact filters individuals by exact last name match (case-insensitive).

func (*FilterQuery) Count

func (fq *FilterQuery) Count() (int, error)

Count returns the number of matching individuals.

func (*FilterQuery) Deceased

func (fq *FilterQuery) Deceased() *FilterQuery

Deceased filters deceased individuals (has death date).

func (*FilterQuery) Execute

func (fq *FilterQuery) Execute() ([]*types.IndividualRecord, error)

Execute runs the filter and returns matching individuals. Uses indexes for fast filtering when possible. If hybrid mode is enabled, uses SQLite for lookups.

func (*FilterQuery) HasChildren

func (fq *FilterQuery) HasChildren() *FilterQuery

HasChildren filters individuals with children. Uses index for fast lookup.

func (*FilterQuery) HasSpouse

func (fq *FilterQuery) HasSpouse() *FilterQuery

HasSpouse filters individuals with spouses. Uses index for fast lookup.

func (*FilterQuery) Living

func (fq *FilterQuery) Living() *FilterQuery

Living filters living individuals (no death date). Uses index for fast lookup.

func (*FilterQuery) NoChildren

func (fq *FilterQuery) NoChildren() *FilterQuery

NoChildren filters individuals without children. Uses index for fast lookup.

func (*FilterQuery) NoSpouse

func (fq *FilterQuery) NoSpouse() *FilterQuery

NoSpouse filters individuals without spouses. Uses index for fast lookup.

func (*FilterQuery) Where

func (fq *FilterQuery) Where(filter Filter) *FilterQuery

Where adds a filter condition.

type Graph

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

Graph represents the graph structure of a GEDCOM tree.

func BuildGraph

func BuildGraph(tree *types.GedcomTree) (*Graph, error)

BuildGraph constructs a graph from a GEDCOM tree. This includes Phase 1 (nodes) and Phase 2 (edges).

func BuildGraphHybrid

func BuildGraphHybrid(tree *types.GedcomTree, sqlitePath, badgerPath string, config *Config) (*Graph, error)

BuildGraphHybrid builds a graph using hybrid storage (SQLite + BadgerDB) This function coordinates the building process by delegating to: - buildGraphInSQLite: Builds indexes in SQLite (see hybrid_sqlite_builder.go) - buildGraphInBadgerDB: Stores graph structure in BadgerDB (see hybrid_badger_builder.go) If config is nil, DefaultConfig() is used.

func BuildGraphHybridPostgres

func BuildGraphHybridPostgres(tree *types.GedcomTree, fileID, badgerPath, databaseURL string, config *Config) (*Graph, error)

BuildGraphHybridPostgres builds a graph using hybrid storage (PostgreSQL + BadgerDB) This function coordinates the building process by delegating to: - buildGraphInPostgreSQL: Builds indexes in PostgreSQL (see hybrid_postgres_builder.go) - buildGraphInBadgerDB: Stores graph structure in BadgerDB (see hybrid_badger_builder.go) If config is nil, DefaultConfig() is used. fileID is required for PostgreSQL to identify which file the data belongs to. databaseURL can be empty, in which case it will use DATABASE_URL environment variable or config.

func BuildGraphHybridWithStorage

func BuildGraphHybridWithStorage(tree *types.GedcomTree, sqlitePath, badgerPath, fileID, databaseURL string, config *Config, usePostgres bool) (*Graph, error)

BuildGraphHybridWithStorage is an internal function that supports both SQLite and PostgreSQL

func BuildGraphLazy

func BuildGraphLazy(tree *types.GedcomTree) (*Graph, error)

BuildGraphLazy constructs a graph skeleton with lazy loading enabled. Nodes and edges are loaded on-demand when accessed.

func CreateTestGraph

func CreateTestGraph(tree *types.GedcomTree) (*Graph, error)

CreateTestGraph creates a Graph from a test tree.

func NewGraph

func NewGraph(tree *types.GedcomTree) *Graph

NewGraph creates a new empty graph with default configuration.

func NewGraphWithConfig

func NewGraphWithConfig(tree *types.GedcomTree, config *Config) *Graph

NewGraphWithConfig creates a new empty graph with the provided configuration.

func (*Graph) AddEdge

func (g *Graph) AddEdge(edge *Edge) error

AddEdge adds an edge to the graph.

func (*Graph) AddEdgeIncremental

func (g *Graph) AddEdgeIncremental(edge *Edge) error

AddEdgeIncremental adds an edge to the graph and updates relationships incrementally.

func (*Graph) AddNode

func (g *Graph) AddNode(node GraphNode) error

AddNode adds a node to the graph (external API - still uses XREF strings).

func (*Graph) AddNodeIncremental

func (g *Graph) AddNodeIncremental(node GraphNode) error

AddNodeIncremental adds a node to the graph and updates relationships incrementally. This is more efficient than rebuilding the entire graph.

func (*Graph) AllPaths

func (g *Graph) AllPaths(fromID, toID string, maxLength int) ([]*Path, error)

AllPaths finds all paths between two nodes using DFS. maxLength limits the maximum path length to avoid infinite loops.

func (*Graph) BFS

func (g *Graph) BFS(startID string, visitor func(GraphNode) bool) error

BFS performs breadth-first search starting from a node. visitor function is called for each visited node. Return false to stop traversal.

func (*Graph) CalculateRelationship

func (g *Graph) CalculateRelationship(fromXref, toXref string) (*RelationshipResult, error)

CalculateRelationship calculates the relationship between two individuals.

func (*Graph) Close

func (g *Graph) Close() error

Close closes the graph and its hybrid storage (SQLite or PostgreSQL)

func (*Graph) CommonAncestors

func (g *Graph) CommonAncestors(indi1Xref, indi2Xref string) ([]*IndividualNode, error)

CommonAncestors finds all common ancestors of two individuals.

func (*Graph) DFS

func (g *Graph) DFS(startID string, visitor func(GraphNode) bool) error

DFS performs depth-first search starting from a node. visitor function is called for each visited node. Return false to stop traversal.

func (*Graph) EdgeCount

func (g *Graph) EdgeCount() int

EdgeCount returns the total number of edges.

func (*Graph) GetAllEdges

func (g *Graph) GetAllEdges() map[string]*Edge

GetAllEdges returns all edges in the graph.

func (*Graph) GetAllFamilies

func (g *Graph) GetAllFamilies() map[string]*FamilyNode

GetAllFamilies returns all FamilyNodes (external API - returns XREF strings).

func (*Graph) GetAllIndividuals

func (g *Graph) GetAllIndividuals() map[string]*IndividualNode

GetAllIndividuals returns all IndividualNodes (external API - returns XREF strings). If hybrid mode is enabled, queries SQLite for all individual IDs. NOTE: In hybrid mode, this returns an empty map because nodes are loaded on-demand. Use FilterQuery.executeHybrid() for efficient querying in hybrid mode.

func (*Graph) GetAllNodes

func (g *Graph) GetAllNodes() map[string]GraphNode

GetAllNodes returns all nodes in the graph (external API - returns XREF strings).

func (*Graph) GetChildren

func (g *Graph) GetChildren(xrefID string) ([]*IndividualNode, error)

GetChildren returns all children of an individual by XREF ID. This is a convenience method that wraps node.Children(). Returns an error if the individual is not found.

func (*Graph) GetComponentCount

func (g *Graph) GetComponentCount() uint32

GetComponentCount returns the number of connected components.

func (*Graph) GetComponentForPerson

func (g *Graph) GetComponentForPerson(personID string) ([]*types.IndividualRecord, error)

GetComponentForPerson returns all individuals in the connected component containing the specified person.

func (*Graph) GetComponentForPersonWithOptions

func (g *Graph) GetComponentForPersonWithOptions(personID string, options *ComponentOptions) ([]*types.IndividualRecord, error)

GetComponentForPersonWithOptions returns connected component with options.

func (*Graph) GetComponentID

func (g *Graph) GetComponentID(xrefID string) uint32

GetComponentID returns the component ID for a node.

func (*Graph) GetComponentSize

func (g *Graph) GetComponentSize(componentID uint32) int

GetComponentSize returns the number of nodes in a component.

func (*Graph) GetEdge

func (g *Graph) GetEdge(edgeID string) *Edge

GetEdge returns an edge by ID.

func (*Graph) GetEdges

func (g *Graph) GetEdges(xrefID string) []*Edge

GetEdges returns all edges for a given node XREF ID (external API - still uses strings).

func (*Graph) GetEvent

func (g *Graph) GetEvent(eventID string) *EventNode

GetEvent returns an EventNode by event ID (external API - still uses strings). If hybrid mode is enabled, loads the node from BadgerDB.

func (*Graph) GetEventsOnDate

func (g *Graph) GetEventsOnDate(year int, month int, day int) ([]EventInfo, error)

GetEventsOnDate returns all events that occur on a specific date. The date can be specified as year, month, day, or a combination.

func (*Graph) GetEventsOnDateByType

func (g *Graph) GetEventsOnDateByType(eventType string, year int, month int, day int) ([]EventInfo, error)

GetEventsOnDateByType returns all events of a specific type that occur on a specific date.

func (*Graph) GetFamily

func (g *Graph) GetFamily(xrefID string) *FamilyNode

GetFamily returns a FamilyNode by xref ID (external API - still uses strings). If lazy mode is enabled, loads the node on-demand. If hybrid mode is enabled, loads the node from BadgerDB.

func (*Graph) GetFamilyChildren

func (g *Graph) GetFamilyChildren(familyXrefID string) ([]*IndividualNode, error)

GetFamilyChildren returns all children of a family by XREF ID. This is a convenience method that wraps familyNode.Children(). Returns an error if the family is not found.

func (*Graph) GetFamilyHusband

func (g *Graph) GetFamilyHusband(familyXrefID string) (*IndividualNode, error)

GetFamilyHusband returns the husband of a family by XREF ID. This is a convenience method that wraps familyNode.Husband(). Returns an error if the family is not found.

func (*Graph) GetFamilyWife

func (g *Graph) GetFamilyWife(familyXrefID string) (*IndividualNode, error)

GetFamilyWife returns the wife of a family by XREF ID. This is a convenience method that wraps familyNode.Wife(). Returns an error if the family is not found.

func (*Graph) GetIndividual

func (g *Graph) GetIndividual(xrefID string) *IndividualNode

GetIndividual returns an IndividualNode by xref ID (external API - still uses strings). If lazy mode is enabled, loads the node on-demand. If hybrid mode is enabled, loads the node from BadgerDB.

func (*Graph) GetMetrics

func (g *Graph) GetMetrics() *Metrics

GetMetrics returns the metrics collector (may be nil if not initialized)

func (*Graph) GetMostCommonGivenNames

func (g *Graph) GetMostCommonGivenNames(limit int) []NameCount

GetMostCommonGivenNames returns the most common first names (given names). Returns top N names sorted by count (descending).

func (*Graph) GetMostCommonSurnames

func (g *Graph) GetMostCommonSurnames(limit int) []NameCount

GetMostCommonSurnames returns the most common last names (surnames). Returns top N names sorted by count (descending).

func (*Graph) GetNode

func (g *Graph) GetNode(xrefID string) GraphNode

GetNode returns a node by XREF ID (external API - still uses strings).

func (*Graph) GetNodeByID

func (g *Graph) GetNodeByID(id uint32) GraphNode

GetNodeByID returns a node by uint32 ID (internal use).

func (*Graph) GetNodeID

func (g *Graph) GetNodeID(xrefID string) uint32

GetNodeID returns the uint32 ID for an XREF string, or 0 if not found.

func (*Graph) GetNote

func (g *Graph) GetNote(xrefID string) *NoteNode

GetNote returns a NoteNode by xref ID (external API - still uses strings). If hybrid mode is enabled, loads the node from BadgerDB.

func (*Graph) GetParents

func (g *Graph) GetParents(xrefID string) ([]*IndividualNode, error)

GetParents returns all parents of an individual by XREF ID. This is a convenience method that wraps node.Parents(). Returns an error if the individual is not found.

func (*Graph) GetRecordsForEvent

func (g *Graph) GetRecordsForEvent(eventID string) ([]GraphNode, error)

GetRecordsForEvent returns all records (individuals, families) that have this event.

func (*Graph) GetRecordsForNote

func (g *Graph) GetRecordsForNote(noteXrefID string) ([]GraphNode, error)

GetRecordsForNote returns all records (individuals, families, events) that reference this note.

func (*Graph) GetRepository

func (g *Graph) GetRepository(xrefID string) *RepositoryNode

GetRepository returns a RepositoryNode by xref ID (external API - still uses strings). If hybrid mode is enabled, loads the node from BadgerDB.

func (*Graph) GetSiblings

func (g *Graph) GetSiblings(xrefID string) ([]*IndividualNode, error)

GetSiblings returns all siblings of an individual by XREF ID. This is a convenience method that wraps node.Siblings(). Returns an error if the individual is not found.

func (*Graph) GetSource

func (g *Graph) GetSource(xrefID string) *SourceNode

GetSource returns a SourceNode by xref ID (external API - still uses strings). If hybrid mode is enabled, loads the node from BadgerDB.

func (*Graph) GetSpouses

func (g *Graph) GetSpouses(xrefID string) ([]*IndividualNode, error)

GetSpouses returns all spouses of an individual by XREF ID. This is a convenience method that wraps node.Spouses(). Returns an error if the individual is not found.

func (*Graph) GetXrefFromID

func (g *Graph) GetXrefFromID(id uint32) string

GetXrefFromID returns the XREF string for a uint32 ID, or empty string if not found.

func (*Graph) LoadComponent

func (g *Graph) LoadComponent(componentID uint32) error

LoadComponent loads all nodes and edges in a component into memory.

func (*Graph) LowestCommonAncestor

func (g *Graph) LowestCommonAncestor(indi1ID, indi2ID string) (*IndividualNode, error)

LowestCommonAncestor finds the lowest (most recent) common ancestor of two individuals. The LCA is the common ancestor that is closest to both individuals (most recent). This is the one that minimizes the maximum distance from both individuals.

func (*Graph) Metrics

func (g *Graph) Metrics() *GraphMetricsQuery

Metrics returns a GraphMetricsQuery for the graph.

func (*Graph) NodeCount

func (g *Graph) NodeCount() int

NodeCount returns the total number of nodes.

func (*Graph) RemoveEdgeIncremental

func (g *Graph) RemoveEdgeIncremental(edgeID string) error

RemoveEdgeIncremental removes an edge from the graph and updates relationships.

func (*Graph) RemoveNodeIncremental

func (g *Graph) RemoveNodeIncremental(xrefID string) error

RemoveNodeIncremental removes a node from the graph and cleans up relationships.

func (*Graph) ShortestPath

func (g *Graph) ShortestPath(fromID, toID string) (*Path, error)

ShortestPath finds the shortest path between two nodes using bidirectional BFS.

func (*Graph) Tree

func (g *Graph) Tree() *types.GedcomTree

Tree returns the underlying GEDCOM tree.

type GraphMetricsQuery

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

GraphMetricsQuery provides graph metrics and analytics.

func NewGraphMetricsQuery

func NewGraphMetricsQuery(graph *Graph) *GraphMetricsQuery

NewGraphMetricsQuery creates a new GraphMetricsQuery.

func (*GraphMetricsQuery) AverageDegree

func (gmq *GraphMetricsQuery) AverageDegree() (float64, error)

AverageDegree calculates the average degree of all nodes.

func (*GraphMetricsQuery) AveragePathLength

func (gmq *GraphMetricsQuery) AveragePathLength() (float64, error)

AveragePathLength calculates the average shortest path length between all pairs.

func (*GraphMetricsQuery) Centrality

func (gmq *GraphMetricsQuery) Centrality(metric CentralityMetric) (map[string]float64, error)

Centrality calculates various centrality measures for all individuals.

func (*GraphMetricsQuery) ConnectedComponents

func (gmq *GraphMetricsQuery) ConnectedComponents() ([][]*types.IndividualRecord, error)

ConnectedComponents returns all connected components in the graph.

func (*GraphMetricsQuery) Degree

func (gmq *GraphMetricsQuery) Degree(xrefID string) (int, error)

Degree returns the degree (number of connections) of an individual.

func (*GraphMetricsQuery) Density

func (gmq *GraphMetricsQuery) Density() (float64, error)

Density calculates the graph density (actual edges / possible edges).

func (*GraphMetricsQuery) Diameter

func (gmq *GraphMetricsQuery) Diameter() (int, error)

Diameter returns the diameter of the family tree (longest shortest path).

func (*GraphMetricsQuery) EdgeCount

func (gmq *GraphMetricsQuery) EdgeCount() int

EdgeCount returns the total number of edges in the graph.

func (*GraphMetricsQuery) InDegree

func (gmq *GraphMetricsQuery) InDegree(xrefID string) (int, error)

InDegree returns the number of incoming connections (parents, spouses).

func (*GraphMetricsQuery) IsConnected

func (gmq *GraphMetricsQuery) IsConnected(xrefID1, xrefID2 string) (bool, error)

IsConnected checks if two individuals are connected (path exists).

func (*GraphMetricsQuery) LongestPath

func (gmq *GraphMetricsQuery) LongestPath() (*Path, error)

LongestPath finds the longest path in the tree.

func (*GraphMetricsQuery) NodeCount

func (gmq *GraphMetricsQuery) NodeCount() int

NodeCount returns the total number of nodes in the graph.

func (*GraphMetricsQuery) OutDegree

func (gmq *GraphMetricsQuery) OutDegree(xrefID string) (int, error)

OutDegree returns the number of outgoing connections (children, spouses).

type GraphNode

type GraphNode interface {
	// ID returns the unique identifier of the node.
	ID() string

	// NodeType returns the type of the node.
	NodeType() NodeType

	// Record returns the original GEDCOM record (if applicable).
	// Returns nil for EventNode which doesn't have a top-level record.
	Record() types.Record

	// InEdges returns all edges pointing TO this node.
	InEdges() []*Edge

	// OutEdges returns all edges pointing FROM this node.
	OutEdges() []*Edge

	// AddInEdge adds an incoming edge to this node.
	AddInEdge(*Edge)

	// AddOutEdge adds an outgoing edge from this node.
	AddOutEdge(*Edge)

	// RemoveInEdge removes an incoming edge from this node.
	RemoveInEdge(*Edge)

	// RemoveOutEdge removes an outgoing edge from this node.
	RemoveOutEdge(*Edge)

	// Neighbors returns all nodes connected to this node (via in or out edges).
	Neighbors() []GraphNode

	// Degree returns the total number of edges (in + out).
	Degree() int

	// InDegree returns the number of incoming edges.
	InDegree() int

	// OutDegree returns the number of outgoing edges.
	OutDegree() int
}

GraphNode is the interface that all graph nodes must implement.

func DeserializeNode

func DeserializeNode(data []byte, graph *Graph) (GraphNode, error)

DeserializeNode deserializes bytes from BadgerDB into a node Reconstructs the record from the GEDCOM tree using the XREF

type GraphValidator

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

GraphValidator validates graph integrity and edge consistency. This validator checks that the graph structure is correct after building.

func NewGraphValidator

func NewGraphValidator(errorManager *types.ErrorManager) *GraphValidator

NewGraphValidator creates a new GraphValidator.

func (*GraphValidator) GetErrorManager

func (gv *GraphValidator) GetErrorManager() *types.ErrorManager

GetErrorManager returns the error manager.

func (*GraphValidator) Validate

func (gv *GraphValidator) Validate(graph *Graph) error

Validate validates the graph structure and returns an error if validation fails. Checks edge consistency, family structure, and relationship integrity.

type HybridCache

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

HybridCache provides LRU caching for hybrid storage operations

func NewHybridCache

func NewHybridCache(nodeCacheSize, xrefCacheSize, queryCacheSize int) (*HybridCache, error)

NewHybridCache creates a new hybrid cache with specified sizes

func (*HybridCache) Clear

func (hc *HybridCache) Clear()

Clear clears all caches

func (*HybridCache) GetIDToXref

func (hc *HybridCache) GetIDToXref(nodeID uint32) (string, bool)

GetIDToXref retrieves XREF from node ID cache

func (*HybridCache) GetNode

func (hc *HybridCache) GetNode(nodeID uint32) (GraphNode, bool)

GetNode retrieves a node from cache

func (*HybridCache) GetQuery

func (hc *HybridCache) GetQuery(key string) ([]uint32, bool)

GetQuery retrieves query results from cache

func (*HybridCache) GetXrefToID

func (hc *HybridCache) GetXrefToID(xref string) (uint32, bool)

GetXrefToID retrieves node ID from XREF cache

func (*HybridCache) SetNode

func (hc *HybridCache) SetNode(nodeID uint32, node GraphNode)

SetNode stores a node in cache

func (*HybridCache) SetQuery

func (hc *HybridCache) SetQuery(key string, nodeIDs []uint32)

SetQuery stores query results in cache

func (*HybridCache) SetXrefToID

func (hc *HybridCache) SetXrefToID(xref string, nodeID uint32)

SetXrefToID stores XREF -> nodeID mapping

func (*HybridCache) Stats

func (hc *HybridCache) Stats() CacheStats

Stats returns cache statistics

type HybridQueryHelper

type HybridQueryHelper interface {
	FindByXref(xref string) (uint32, error)
	FindXrefByID(nodeID uint32) (string, error)
	FindByName(pattern string) ([]uint32, error)
	FindByNameExact(name string) ([]uint32, error)
	FindByNameStarts(prefix string) ([]uint32, error)
	FindByBirthDate(start, end time.Time) ([]uint32, error)
	FindByBirthPlace(place string) ([]uint32, error)
	FindBySex(sex string) ([]uint32, error)
	HasChildren(nodeID uint32) (bool, error)
	HasSpouse(nodeID uint32) (bool, error)
	IsLiving(nodeID uint32) (bool, error)
	GetAllIndividualIDs() ([]uint32, error)
}

HybridQueryHelper is an interface for both SQLite and PostgreSQL query helpers

type HybridQueryHelpers

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

HybridQueryHelpers provides SQLite query methods for hybrid storage

func NewHybridQueryHelpers

func NewHybridQueryHelpers(db *sql.DB) (*HybridQueryHelpers, error)

NewHybridQueryHelpers creates a new helper instance and prepares statements

func (*HybridQueryHelpers) Close

func (h *HybridQueryHelpers) Close() error

Close closes all prepared statements

func (*HybridQueryHelpers) FindByBirthDate

func (h *HybridQueryHelpers) FindByBirthDate(start, end time.Time) ([]uint32, error)

FindByBirthDate finds node IDs by birth date range

func (*HybridQueryHelpers) FindByBirthPlace

func (h *HybridQueryHelpers) FindByBirthPlace(place string) ([]uint32, error)

FindByBirthPlace finds node IDs by birth place (substring match, case-insensitive)

func (*HybridQueryHelpers) FindByName

func (h *HybridQueryHelpers) FindByName(pattern string) ([]uint32, error)

FindByName finds node IDs by name (substring match, case-insensitive)

func (*HybridQueryHelpers) FindByNameExact

func (h *HybridQueryHelpers) FindByNameExact(name string) ([]uint32, error)

FindByNameExact finds node IDs by exact name match (case-insensitive)

func (*HybridQueryHelpers) FindByNameStarts

func (h *HybridQueryHelpers) FindByNameStarts(prefix string) ([]uint32, error)

FindByNameStarts finds node IDs by name prefix (case-insensitive)

func (*HybridQueryHelpers) FindBySex

func (h *HybridQueryHelpers) FindBySex(sex string) ([]uint32, error)

FindBySex finds node IDs by sex

func (*HybridQueryHelpers) FindByXref

func (h *HybridQueryHelpers) FindByXref(xref string) (uint32, error)

FindByXref returns node ID for a given XREF

func (*HybridQueryHelpers) FindXrefByID

func (h *HybridQueryHelpers) FindXrefByID(nodeID uint32) (string, error)

FindXrefByID returns XREF for a given node ID

func (*HybridQueryHelpers) GetAllIndividualIDs

func (h *HybridQueryHelpers) GetAllIndividualIDs() ([]uint32, error)

GetAllIndividualIDs returns all individual node IDs

func (*HybridQueryHelpers) HasChildren

func (h *HybridQueryHelpers) HasChildren(nodeID uint32) (bool, error)

HasChildren checks if a node has children

func (*HybridQueryHelpers) HasSpouse

func (h *HybridQueryHelpers) HasSpouse(nodeID uint32) (bool, error)

HasSpouse checks if a node has a spouse

func (*HybridQueryHelpers) IsLiving

func (h *HybridQueryHelpers) IsLiving(nodeID uint32) (bool, error)

IsLiving checks if a node is living

type HybridQueryHelpersPostgres

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

HybridQueryHelpersPostgres provides PostgreSQL query methods for hybrid storage All queries include file_id for multi-file support

func NewHybridQueryHelpersPostgres

func NewHybridQueryHelpersPostgres(db *sql.DB, fileID string) (*HybridQueryHelpersPostgres, error)

NewHybridQueryHelpersPostgres creates a new PostgreSQL helper instance and prepares statements

func (*HybridQueryHelpersPostgres) Close

func (h *HybridQueryHelpersPostgres) Close() error

Close closes all prepared statements

func (*HybridQueryHelpersPostgres) FindByBirthDate

func (h *HybridQueryHelpersPostgres) FindByBirthDate(start, end time.Time) ([]uint32, error)

FindByBirthDate finds node IDs by birth date range

func (*HybridQueryHelpersPostgres) FindByBirthPlace

func (h *HybridQueryHelpersPostgres) FindByBirthPlace(place string) ([]uint32, error)

FindByBirthPlace finds node IDs by birth place (substring match, case-insensitive)

func (*HybridQueryHelpersPostgres) FindByName

func (h *HybridQueryHelpersPostgres) FindByName(pattern string) ([]uint32, error)

FindByName finds node IDs by name (substring match, case-insensitive)

func (*HybridQueryHelpersPostgres) FindByNameExact

func (h *HybridQueryHelpersPostgres) FindByNameExact(name string) ([]uint32, error)

FindByNameExact finds node IDs by exact name match (case-insensitive)

func (*HybridQueryHelpersPostgres) FindByNameStarts

func (h *HybridQueryHelpersPostgres) FindByNameStarts(prefix string) ([]uint32, error)

FindByNameStarts finds node IDs by name prefix (case-insensitive)

func (*HybridQueryHelpersPostgres) FindBySex

func (h *HybridQueryHelpersPostgres) FindBySex(sex string) ([]uint32, error)

FindBySex finds node IDs by sex

func (*HybridQueryHelpersPostgres) FindByXref

func (h *HybridQueryHelpersPostgres) FindByXref(xref string) (uint32, error)

FindByXref returns node ID for a given XREF

func (*HybridQueryHelpersPostgres) FindXrefByID

func (h *HybridQueryHelpersPostgres) FindXrefByID(nodeID uint32) (string, error)

FindXrefByID returns XREF for a given node ID

func (*HybridQueryHelpersPostgres) GetAllIndividualIDs

func (h *HybridQueryHelpersPostgres) GetAllIndividualIDs() ([]uint32, error)

GetAllIndividualIDs returns all individual node IDs

func (*HybridQueryHelpersPostgres) HasChildren

func (h *HybridQueryHelpersPostgres) HasChildren(nodeID uint32) (bool, error)

HasChildren checks if a node has children

func (*HybridQueryHelpersPostgres) HasSpouse

func (h *HybridQueryHelpersPostgres) HasSpouse(nodeID uint32) (bool, error)

HasSpouse checks if a node has a spouse

func (*HybridQueryHelpersPostgres) IsLiving

func (h *HybridQueryHelpersPostgres) IsLiving(nodeID uint32) (bool, error)

IsLiving checks if a node is living

type HybridStorage

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

HybridStorage manages both SQLite and BadgerDB databases

func NewHybridStorage

func NewHybridStorage(sqlitePath, badgerPath string, config *Config) (*HybridStorage, error)

NewHybridStorage creates a new hybrid storage instance If config is nil, DefaultConfig() is used.

func (*HybridStorage) BadgerDB

func (hs *HybridStorage) BadgerDB() *badger.DB

BadgerDB returns the BadgerDB database instance

func (*HybridStorage) Close

func (hs *HybridStorage) Close() error

Close closes both databases

func (*HybridStorage) SQLite

func (hs *HybridStorage) SQLite() *sql.DB

SQLite returns the SQLite database connection

type HybridStoragePostgres

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

HybridStoragePostgres manages both PostgreSQL and BadgerDB databases This is similar to HybridStorage but uses PostgreSQL instead of SQLite

func NewHybridStoragePostgres

func NewHybridStoragePostgres(fileID, badgerPath, databaseURL string, config *Config) (*HybridStoragePostgres, error)

NewHybridStoragePostgres creates a new PostgreSQL-based hybrid storage instance If config is nil, DefaultConfig() is used. databaseURL can be empty, in which case it will use DATABASE_URL environment variable

func (*HybridStoragePostgres) BadgerDB

func (hs *HybridStoragePostgres) BadgerDB() *badger.DB

BadgerDB returns the BadgerDB database instance

func (*HybridStoragePostgres) Close

func (hs *HybridStoragePostgres) Close() error

Close closes both databases

func (*HybridStoragePostgres) FileID

func (hs *HybridStoragePostgres) FileID() string

FileID returns the file ID for this storage instance

func (*HybridStoragePostgres) PostgreSQL

func (hs *HybridStoragePostgres) PostgreSQL() *sql.DB

PostgreSQL returns the PostgreSQL database connection

type IndividualNode

type IndividualNode struct {
	*BaseNode
	Individual *types.IndividualRecord
	// contains filtered or unexported fields
}

IndividualNode represents an individual person in the genealogy.

func CollectIndividuals

func CollectIndividuals(graph *Graph, filter func(*IndividualNode) bool) []*IndividualNode

CollectIndividuals collects all individuals matching the filter.

func NewIndividualNode

func NewIndividualNode(xrefID string, record *types.IndividualRecord) *IndividualNode

NewIndividualNode creates a new IndividualNode.

func (*IndividualNode) Children

func (node *IndividualNode) Children() []*IndividualNode

Children returns all children of this individual. Computes children from edges (edge-based traversal). This is the recommended way to get relationships - use graph nodes, not records.

func (*IndividualNode) Parents

func (node *IndividualNode) Parents() []*IndividualNode

Parents returns all parents of this individual. Computes parents from edges (edge-based traversal). This is the recommended way to get relationships - use graph nodes, not records.

func (*IndividualNode) Siblings

func (node *IndividualNode) Siblings() []*IndividualNode

Siblings returns all siblings of this individual. Computes siblings from edges (edge-based traversal). This is the recommended way to get relationships - use graph nodes, not records.

func (*IndividualNode) Spouses

func (node *IndividualNode) Spouses() []*IndividualNode

Spouses returns all spouses of this individual. Computes spouses from edges (edge-based traversal). This is the recommended way to get relationships - use graph nodes, not records.

type IndividualQuery

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

IndividualQuery represents a query starting from a specific individual.

func (*IndividualQuery) Ancestors

func (iq *IndividualQuery) Ancestors() *AncestorQuery

Ancestors finds all ancestors of this individual.

func (*IndividualQuery) Children

func (iq *IndividualQuery) Children() ([]*types.IndividualRecord, error)

Children returns direct children. Results are cached for repeated queries.

func (*IndividualQuery) CommonAncestors

func (iq *IndividualQuery) CommonAncestors(otherXrefID string) ([]*types.IndividualRecord, error)

CommonAncestors finds common ancestors with another individual.

func (*IndividualQuery) Cousins

func (iq *IndividualQuery) Cousins(degree int) ([]*types.IndividualRecord, error)

Cousins finds cousins (configurable degree).

func (*IndividualQuery) Descendants

func (iq *IndividualQuery) Descendants() *DescendantQuery

Descendants finds all descendants of this individual.

func (*IndividualQuery) GetAllNotes

func (iq *IndividualQuery) GetAllNotes() ([]NoteInfo, error)

GetAllNotesForIndividual returns all notes associated with an individual, including both referenced notes (via NOTE xrefs) and inline notes (embedded in the record).

func (*IndividualQuery) GetEvents

func (iq *IndividualQuery) GetEvents() ([]EventInfo, error)

GetEventsForIndividual returns all events associated with an individual.

func (*IndividualQuery) GetSubtree

func (iq *IndividualQuery) GetSubtree() *SubtreeQuery

GetSubtree returns ancestors and descendants of this individual.

func (*IndividualQuery) Grandchildren

func (iq *IndividualQuery) Grandchildren() ([]*types.IndividualRecord, error)

Grandchildren returns grandchildren.

func (*IndividualQuery) Grandparents

func (iq *IndividualQuery) Grandparents() ([]*types.IndividualRecord, error)

Grandparents returns grandparents.

func (*IndividualQuery) Nephews

func (iq *IndividualQuery) Nephews() ([]*types.IndividualRecord, error)

Nephews finds nephews/nieces.

func (*IndividualQuery) Parents

func (iq *IndividualQuery) Parents() ([]*types.IndividualRecord, error)

Parents returns direct parents. Results are cached for repeated queries.

func (*IndividualQuery) PathTo

func (iq *IndividualQuery) PathTo(otherXrefID string) *PathQuery

PathTo finds path(s) to another individual.

func (*IndividualQuery) RelationshipTo

func (iq *IndividualQuery) RelationshipTo(otherXrefID string) *RelationshipQuery

RelationshipTo finds relationship to another individual.

func (*IndividualQuery) RelationshipToResult

func (iq *IndividualQuery) RelationshipToResult(otherXrefID string) (*RelationshipResult, error)

RelationshipTo returns the relationship result directly (convenience method).

func (*IndividualQuery) Siblings

func (iq *IndividualQuery) Siblings() ([]*types.IndividualRecord, error)

Siblings returns siblings (full and half).

func (*IndividualQuery) Spouses

func (iq *IndividualQuery) Spouses() ([]*types.IndividualRecord, error)

Spouses returns all spouses.

func (*IndividualQuery) Uncles

func (iq *IndividualQuery) Uncles() ([]*types.IndividualRecord, error)

Uncles finds uncles/aunts.

type LazyGraph

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

LazyGraph extends Graph with lazy loading capabilities. This is embedded in Graph to add lazy loading without breaking existing code.

type Metrics

type Metrics struct {

	// Query metrics
	QueryCount     int64
	QueryTotalTime time.Duration
	QueryAvgTime   time.Duration
	QueryMaxTime   time.Duration
	QueryMinTime   time.Duration

	// Cache metrics
	CacheHits    int64
	CacheMisses  int64
	CacheHitRate float64

	// Storage metrics
	StorageReads     int64
	StorageWrites    int64
	StorageReadTime  time.Duration
	StorageWriteTime time.Duration

	// Graph metrics
	NodesLoaded    int64
	EdgesLoaded    int64
	GraphBuildTime time.Duration

	// Error metrics
	ErrorCount  int64
	ErrorByType map[string]int64
	// contains filtered or unexported fields
}

Metrics collects performance and usage metrics

func NewMetrics

func NewMetrics() *Metrics

NewMetrics creates a new Metrics collector

func (*Metrics) GetSnapshot

func (m *Metrics) GetSnapshot() MetricsSnapshot

GetSnapshot returns a snapshot of current metrics

func (*Metrics) RecordCacheHit

func (m *Metrics) RecordCacheHit()

RecordCacheHit records a cache hit

func (*Metrics) RecordCacheMiss

func (m *Metrics) RecordCacheMiss()

RecordCacheMiss records a cache miss

func (*Metrics) RecordEdgeLoad

func (m *Metrics) RecordEdgeLoad()

RecordEdgeLoad records an edge load operation

func (*Metrics) RecordError

func (m *Metrics) RecordError(errorType string)

RecordError records an error occurrence

func (*Metrics) RecordGraphBuild

func (m *Metrics) RecordGraphBuild(duration time.Duration)

RecordGraphBuild records graph build time

func (*Metrics) RecordNodeLoad

func (m *Metrics) RecordNodeLoad()

RecordNodeLoad records a node load operation

func (*Metrics) RecordQuery

func (m *Metrics) RecordQuery(duration time.Duration)

RecordQuery records a query execution

func (*Metrics) RecordStorageRead

func (m *Metrics) RecordStorageRead(duration time.Duration)

RecordStorageRead records a storage read operation

func (*Metrics) RecordStorageWrite

func (m *Metrics) RecordStorageWrite(duration time.Duration)

RecordStorageWrite records a storage write operation

func (*Metrics) Reset

func (m *Metrics) Reset()

Reset resets all metrics

type MetricsSnapshot

type MetricsSnapshot struct {
	QueryCount       int64
	QueryAvgTime     time.Duration
	QueryMaxTime     time.Duration
	QueryMinTime     time.Duration
	CacheHits        int64
	CacheMisses      int64
	CacheHitRate     float64
	StorageReads     int64
	StorageWrites    int64
	StorageReadTime  time.Duration
	StorageWriteTime time.Duration
	NodesLoaded      int64
	EdgesLoaded      int64
	GraphBuildTime   time.Duration
	ErrorCount       int64
	ErrorByType      map[string]int64
}

MetricsSnapshot is a read-only snapshot of metrics

type MultiIndividualQuery

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

MultiIndividualQuery represents a query starting from multiple individuals.

func (*MultiIndividualQuery) Ancestors

func (miq *MultiIndividualQuery) Ancestors() ([]*types.IndividualRecord, error)

Ancestors finds all ancestors of all individuals in the query.

func (*MultiIndividualQuery) CommonAncestors

func (miq *MultiIndividualQuery) CommonAncestors() ([]*types.IndividualRecord, error)

CommonAncestors finds common ancestors across all individuals in the query.

func (*MultiIndividualQuery) Count

func (miq *MultiIndividualQuery) Count() int

Count returns the number of individuals in the query.

func (*MultiIndividualQuery) Descendants

func (miq *MultiIndividualQuery) Descendants() ([]*types.IndividualRecord, error)

Descendants finds all descendants of all individuals in the query.

func (*MultiIndividualQuery) Execute

func (miq *MultiIndividualQuery) Execute() ([]*types.IndividualRecord, error)

Execute returns all individual records in the query.

func (*MultiIndividualQuery) Intersection

func (miq *MultiIndividualQuery) Intersection(queries ...func(*IndividualQuery) ([]*types.IndividualRecord, error)) ([]*types.IndividualRecord, error)

Intersection returns the intersection of results from multiple individual queries.

func (*MultiIndividualQuery) Union

func (miq *MultiIndividualQuery) Union(queries ...func(*IndividualQuery) ([]*types.IndividualRecord, error)) ([]*types.IndividualRecord, error)

Union returns the union of results from multiple individual queries. This is useful when you want to combine results from different queries.

type NameCollectionQuery

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

NameCollectionQuery provides collection operations on names.

func NewNameCollectionQuery

func NewNameCollectionQuery(graph *Graph) *NameCollectionQuery

NewNameCollectionQuery creates a new NameCollectionQuery.

func (*NameCollectionQuery) All

func (ncq *NameCollectionQuery) All() ([]NameInfo, error)

All returns all names from all individuals.

func (*NameCollectionQuery) By

By specifies uniqueness criteria.

func (*NameCollectionQuery) Count

func (ncq *NameCollectionQuery) Count() (int, error)

Count returns the number of unique names.

func (*NameCollectionQuery) Execute

func (ncq *NameCollectionQuery) Execute() ([]string, error)

Execute runs the query and returns unique name strings based on criteria.

func (*NameCollectionQuery) Unique

Unique returns unique names based on criteria.

type NameCount

type NameCount struct {
	Name  string
	Count int
}

NameCount represents a name with its occurrence count.

type NameInfo

type NameInfo struct {
	IndividualXref string
	Name           *types.GedcomName
	IsPrimary      bool
}

NameInfo represents a name with context.

type NameUniqueBy

type NameUniqueBy string

NameUniqueBy specifies what makes a name unique.

const (
	NameUniqueByFullName     NameUniqueBy = "full_name"     // By full name string
	NameUniqueByGiven        NameUniqueBy = "given"         // By given name
	NameUniqueBySurname      NameUniqueBy = "surname"       // By surname
	NameUniqueByGivenSurname NameUniqueBy = "given_surname" // By given + surname
	NameUniqueBySurnameGiven NameUniqueBy = "surname_given" // By surname + given
)

type NodeData

type NodeData struct {
	ID       uint32
	Xref     string
	NodeType NodeType
	// Event-specific fields (only used for NodeTypeEvent)
	EventType string
	EventData map[string]interface{}
}

NodeData represents serialized node data for BadgerDB Note: We don't serialize the full record - we store the XREF and reconstruct from tree For EventNode, we also store EventType and EventData since events don't have top-level records

type NodeMetadata

type NodeMetadata struct {
	XrefID      string
	NodeType    NodeType
	ComponentID uint32 // For graph partitioning (0 = unassigned)
	Loaded      bool   // Whether the node is currently loaded in memory
}

NodeMetadata stores minimal information about a node for lazy loading.

type NodeType

type NodeType string

NodeType represents the type of a graph node.

const (
	NodeTypeIndividual NodeType = "individual"
	NodeTypeFamily     NodeType = "family"
	NodeTypeNote       NodeType = "note"
	NodeTypeSource     NodeType = "source"
	NodeTypeRepository NodeType = "repository"
	NodeTypeEvent      NodeType = "event"
)

type NoteInfo

type NoteInfo struct {
	XrefID     string            // Empty for inline notes
	Text       string            // Note text content
	IsInline   bool              // True if inline, false if referenced
	NoteRecord *types.NoteRecord // nil for inline notes
}

NoteInfo represents information about a note (either referenced or inline).

type NoteNode

type NoteNode struct {
	*BaseNode
	Note *types.NoteRecord

	// Cached relationships
	ReferencedBy []GraphNode
}

NoteNode represents a note record.

func NewNoteNode

func NewNoteNode(xrefID string, record *types.NoteRecord) *NoteNode

NewNoteNode creates a new NoteNode.

type Order

type Order string

Order represents the traversal order.

const (
	OrderBFS Order = "BFS" // Breadth-first search
	OrderDFS Order = "DFS" // Depth-first search
)

type Path

type Path struct {
	Nodes  []GraphNode
	Edges  []*Edge
	Length int
	Type   PathType
}

Path represents a path between two nodes in the graph.

type PathOptions

type PathOptions struct {
	MaxLength      int  // Maximum path length (0 = unlimited, but defaults to 10)
	IncludeMarital bool // Include marital relationships
	IncludeBlood   bool // Include blood relationships
	ShortestOnly   bool // Return only shortest path
}

PathOptions holds configuration for path queries.

func NewPathOptions

func NewPathOptions() *PathOptions

NewPathOptions creates new PathOptions with defaults.

type PathQuery

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

PathQuery represents a query for paths between two individuals.

func (*PathQuery) All

func (pq *PathQuery) All() ([]*Path, error)

All returns all paths between the two individuals.

func (*PathQuery) Count

func (pq *PathQuery) Count() (int, error)

Count returns the number of paths.

func (*PathQuery) IncludeBlood

func (pq *PathQuery) IncludeBlood(include bool) *PathQuery

IncludeBlood sets whether to include blood relationships.

func (*PathQuery) IncludeMarital

func (pq *PathQuery) IncludeMarital(include bool) *PathQuery

IncludeMarital sets whether to include marital relationships.

func (*PathQuery) MaxLength

func (pq *PathQuery) MaxLength(n int) *PathQuery

MaxLength sets the maximum path length.

func (*PathQuery) Shortest

func (pq *PathQuery) Shortest() (*Path, error)

Shortest returns the shortest path between the two individuals.

func (*PathQuery) ShortestOnly

func (pq *PathQuery) ShortestOnly(shortest bool) *PathQuery

ShortestOnly sets whether to return only the shortest path.

type PathType

type PathType string

PathType represents the type of path (blood, marital, mixed).

const (
	PathTypeBlood   PathType = "blood"   // Only blood relationships
	PathTypeMarital PathType = "marital" // Only marital relationships
	PathTypeMixed   PathType = "mixed"   // Mixed relationships
)

type PlaceCollectionQuery

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

PlaceCollectionQuery provides collection operations on places.

func NewPlaceCollectionQuery

func NewPlaceCollectionQuery(graph *Graph) *PlaceCollectionQuery

NewPlaceCollectionQuery creates a new PlaceCollectionQuery.

func (*PlaceCollectionQuery) All

func (pcq *PlaceCollectionQuery) All() ([]string, error)

All returns all places from all events.

func (*PlaceCollectionQuery) By

By specifies uniqueness criteria.

func (*PlaceCollectionQuery) Count

func (pcq *PlaceCollectionQuery) Count() (int, error)

Count returns the number of unique places.

func (*PlaceCollectionQuery) Execute

func (pcq *PlaceCollectionQuery) Execute() ([]string, error)

Execute runs the query and returns unique places based on criteria.

func (*PlaceCollectionQuery) FromBirth

func (pcq *PlaceCollectionQuery) FromBirth() *PlaceCollectionQuery

FromBirth only includes birth places.

func (*PlaceCollectionQuery) FromDeath

func (pcq *PlaceCollectionQuery) FromDeath() *PlaceCollectionQuery

FromDeath only includes death places.

func (*PlaceCollectionQuery) FromMarriage

func (pcq *PlaceCollectionQuery) FromMarriage() *PlaceCollectionQuery

FromMarriage only includes marriage places.

func (*PlaceCollectionQuery) Unique

Unique returns unique places based on criteria.

type PlaceUniqueBy

type PlaceUniqueBy string

PlaceUniqueBy specifies what makes a place unique.

const (
	PlaceUniqueByFullString PlaceUniqueBy = "full_string" // By full place string
	PlaceUniqueByCity       PlaceUniqueBy = "city"        // By city component
	PlaceUniqueByState      PlaceUniqueBy = "state"       // By state component
	PlaceUniqueByCountry    PlaceUniqueBy = "country"     // By country component
	PlaceUniqueByCityState  PlaceUniqueBy = "city_state"  // By city + state
)

type QueryBuilder

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

QueryBuilder is the entry point for building queries on a GEDCOM graph.

func CreateTestQuery

func CreateTestQuery(tree *types.GedcomTree) (*QueryBuilder, error)

CreateTestQuery creates a QueryBuilder from a test tree.

func NewQuery

func NewQuery(tree *types.GedcomTree) (*QueryBuilder, error)

NewQuery creates a new query builder from a GEDCOM tree. It builds the graph automatically (eager loading).

func NewQueryFromGraph

func NewQueryFromGraph(graph *Graph) *QueryBuilder

NewQueryFromGraph creates a new query builder from an existing graph.

func NewQueryLazy

func NewQueryLazy(tree *types.GedcomTree) (*QueryBuilder, error)

NewQueryLazy creates a new query builder with lazy loading enabled. Nodes and edges are loaded on-demand when accessed. This is more memory-efficient for large datasets.

func (*QueryBuilder) AllEvents

func (qb *QueryBuilder) AllEvents() ([]EventInfo, error)

AllEvents returns all events from all individuals and families in the tree. Deprecated: Use Events().All() instead.

func (*QueryBuilder) AllFamilies

func (qb *QueryBuilder) AllFamilies() ([]*types.FamilyRecord, error)

AllFamilies returns all family records in the tree. Deprecated: Use Families().All() instead.

func (*QueryBuilder) AllIndividuals

func (qb *QueryBuilder) AllIndividuals() *MultiIndividualQuery

AllIndividuals starts a query from all individuals.

func (*QueryBuilder) AllPlaces

func (qb *QueryBuilder) AllPlaces() ([]string, error)

AllPlaces returns all unique places found in the tree. Places are extracted from birth, death, marriage, and other event locations. Deprecated: Use Places().All() instead.

func (*QueryBuilder) Events

func (qb *QueryBuilder) Events() *EventCollectionQuery

Events returns an EventCollectionQuery for collection operations on events.

func (*QueryBuilder) Families

func (qb *QueryBuilder) Families() *FamilyCollectionQuery

Families returns a FamilyCollectionQuery for collection operations on families.

func (*QueryBuilder) Family

func (qb *QueryBuilder) Family(xrefID string) *FamilyQuery

Family starts a query from a family.

func (*QueryBuilder) Filter

func (qb *QueryBuilder) Filter() *FilterQuery

Filter starts a filter query on all individuals.

func (*QueryBuilder) Graph

func (qb *QueryBuilder) Graph() *Graph

Graph returns the internal graph representation for advanced operations.

func (*QueryBuilder) Individual

func (qb *QueryBuilder) Individual(xrefID string) *IndividualQuery

Individual starts a query from a specific individual.

func (*QueryBuilder) Individuals

func (qb *QueryBuilder) Individuals(xrefIDs ...string) *MultiIndividualQuery

Individuals starts a query from multiple individuals.

func (*QueryBuilder) Metrics

func (qb *QueryBuilder) Metrics() *GraphMetricsQuery

Metrics returns a GraphMetricsQuery for graph analytics.

func (*QueryBuilder) Names

func (qb *QueryBuilder) Names() *NameCollectionQuery

Names returns a NameCollectionQuery for collection operations on names.

func (*QueryBuilder) Places

func (qb *QueryBuilder) Places() *PlaceCollectionQuery

Places returns a PlaceCollectionQuery for collection operations on places.

func (*QueryBuilder) UniqueNames

func (qb *QueryBuilder) UniqueNames() (map[string][]string, error)

UniqueNames returns all unique names found in the tree. Returns a map with "given" and "surname" keys, each containing a slice of unique names. Uses GedcomName parsing for accurate extraction of name components. Deprecated: Use Names().Unique().By(NameUniqueByGiven).Execute() and Names().Unique().By(NameUniqueBySurname).Execute() instead.

type RelationshipQuery

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

RelationshipQuery represents a query for the relationship between two individuals.

func (*RelationshipQuery) Execute

func (rq *RelationshipQuery) Execute() (*RelationshipResult, error)

Execute calculates and returns the relationship result.

type RelationshipResult

type RelationshipResult struct {
	RelationshipType string
	Degree           int
	Removal          int
	Path             *Path
	AllPaths         []*Path
	IsDirect         bool
	IsAncestral      bool
	IsDescendant     bool
	IsCollateral     bool
}

RelationshipResult represents the relationship between two individuals.

func (*RelationshipResult) GetRelationshipType

func (rr *RelationshipResult) GetRelationshipType() string

GetRelationshipType returns the human-readable relationship type.

func (*RelationshipResult) IsBloodRelation

func (rr *RelationshipResult) IsBloodRelation() bool

IsBloodRelation checks if this is a blood relation.

func (*RelationshipResult) IsMaritalRelation

func (rr *RelationshipResult) IsMaritalRelation() bool

IsMaritalRelation checks if this is a marital relation.

type RepositoryNode

type RepositoryNode struct {
	*BaseNode
	Repository *types.RepositoryRecord

	// Cached relationships
	Sources []*SourceNode
}

RepositoryNode represents a repository where sources are stored.

func NewRepositoryNode

func NewRepositoryNode(xrefID string, record *types.RepositoryRecord) *RepositoryNode

NewRepositoryNode creates a new RepositoryNode.

type SourceNode

type SourceNode struct {
	*BaseNode
	Source *types.SourceRecord

	// Cached relationships
	ReferencedBy []GraphNode
	Repository   *RepositoryNode
}

SourceNode represents a source citation record.

func NewSourceNode

func NewSourceNode(xrefID string, record *types.SourceRecord) *SourceNode

NewSourceNode creates a new SourceNode.

type SubtreeOptions

type SubtreeOptions struct {
	AncestorGenerations   int                                // Max ancestor generations (0 = unlimited)
	DescendantGenerations int                                // Max descendant generations (0 = unlimited)
	IncludeSelf           bool                               // Include starting individual
	IncludeSiblings       bool                               // Include siblings
	IncludeSpouses        bool                               // Include spouses
	Filter                func(*types.IndividualRecord) bool // Custom filter function
}

SubtreeOptions holds configuration for subtree queries.

func NewSubtreeOptions

func NewSubtreeOptions() *SubtreeOptions

NewSubtreeOptions creates new SubtreeOptions with defaults.

type SubtreeQuery

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

SubtreeQuery represents a query for a subtree (ancestors + descendants).

func (*SubtreeQuery) AncestorGenerations

func (sq *SubtreeQuery) AncestorGenerations(n int) *SubtreeQuery

AncestorGenerations limits the depth of ancestor search.

func (*SubtreeQuery) Count

func (sq *SubtreeQuery) Count() (int, error)

Count returns the total number of individuals in the subtree.

func (*SubtreeQuery) DescendantGenerations

func (sq *SubtreeQuery) DescendantGenerations(n int) *SubtreeQuery

DescendantGenerations limits the depth of descendant search.

func (*SubtreeQuery) ExcludeSelf

func (sq *SubtreeQuery) ExcludeSelf() *SubtreeQuery

ExcludeSelf excludes the starting individual from results.

func (*SubtreeQuery) Execute

func (sq *SubtreeQuery) Execute() (*SubtreeResult, error)

Execute runs the query and returns subtree results.

func (*SubtreeQuery) ExecuteRecords

func (sq *SubtreeQuery) ExecuteRecords() ([]*types.IndividualRecord, error)

ExecuteRecords returns just the combined list of records (convenience method).

func (*SubtreeQuery) Filter

func (sq *SubtreeQuery) Filter(fn func(*types.IndividualRecord) bool) *SubtreeQuery

Filter applies a custom filter function to results.

func (*SubtreeQuery) IncludeSelf

func (sq *SubtreeQuery) IncludeSelf() *SubtreeQuery

IncludeSelf includes the starting individual in results.

func (*SubtreeQuery) IncludeSiblings

func (sq *SubtreeQuery) IncludeSiblings() *SubtreeQuery

IncludeSiblings includes siblings in results.

func (*SubtreeQuery) IncludeSpouses

func (sq *SubtreeQuery) IncludeSpouses() *SubtreeQuery

IncludeSpouses includes spouses in results.

type SubtreeResult

type SubtreeResult struct {
	Root        *types.IndividualRecord   // The starting individual
	Ancestors   []*types.IndividualRecord // Ancestors (upward)
	Descendants []*types.IndividualRecord // Descendants (downward)
	Siblings    []*types.IndividualRecord // Siblings (if included)
	Spouses     []*types.IndividualRecord // Spouses (if included)
	All         []*types.IndividualRecord // Combined list (deduplicated)
}

SubtreeResult represents the result of a subtree query.

type TimeoutConfig

type TimeoutConfig struct {
	// Database operation timeouts
	SQLiteQueryTimeout time.Duration `json:"sqlite_query_timeout"` // Default: 30s
	BadgerDBTimeout    time.Duration `json:"badgerdb_timeout"`     // Default: 10s

	// Graph building timeout
	BuildTimeout time.Duration `json:"build_timeout"` // Default: 5m

	// Query execution timeout
	QueryTimeout time.Duration `json:"query_timeout"` // Default: 1m
}

TimeoutConfig holds timeout configurations

func (TimeoutConfig) MarshalJSON

func (tc TimeoutConfig) MarshalJSON() ([]byte, error)

MarshalJSON implements custom JSON marshaling for TimeoutConfig to output duration as human-readable strings

func (*TimeoutConfig) UnmarshalJSON

func (tc *TimeoutConfig) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshaling for TimeoutConfig to support duration strings like "30s", "5m", "1h", etc.

Jump to

Keyboard shortcuts

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