🔍 Code Extractor

class Subgraph

Maturity: 36

A class representing a graph subgraph containing nodes and relationships, with support for set operations and graph binding/unbinding.

File:
/tf/active/vicechatdev/neo4j_driver/neo4j_objects.py
Lines:
393 - 459
Complexity:
moderate

Purpose

The Subgraph class models a subset of a graph structure, managing collections of nodes and relationships. It provides graph algebra operations (union, intersection, difference, symmetric difference) and supports binding/unbinding from a parent graph. This is typically used in graph database operations to work with portions of larger graphs, allowing manipulation and combination of graph fragments.

Source Code

class Subgraph():
    
    def __init__(self, nodes=None, relationships=None, graph=None):
        self._graph = graph
        self._nodes = frozenset(nodes or [])
        self._relationships = frozenset(relationships or [])
        self._nodes |= frozenset(chain.from_iterable(r.nodes for r in self._relationships))
        
    @property
    def nodes(self):
        return set(self._nodes)
    
    @property
    def relationships(self):
        return set(self._relationships)
    
    @property
    def graph(self):
        return self._graph
    
    @graph.setter
    def graph(self, graph):
        self._graph = graph
    
    def unbind(self):
        """Returns an unbound copy of itself"""
        out = Subgraph()
        created_nodes = []
        for r in self.relationships:
            if r.start_node['UID'] in created_nodes:
                start = [i for i in out.nodes if i['UID'] == r.start_node['UID']][0]
            else:
                start = r.start_node.unbind()
                created_nodes.append(start['UID'])
            if r.end_node['UID'] in created_nodes:
                end = [i for i in out.nodes if i['UID'] == r.end_node['UID']][0]
            else:
                end = r.end_node.unbind()
                created_nodes.append(end['UID'])
            out = out | Relationship(start, _Relationship(*r.labels, **r.relationship), end)
        return out
    
    def __str__(self):
        return "Nodes(%s), \nRelationships(%s)" % (self.nodes,
                                                   self.relationships)
    
    def __repr__(self):
        return "Nodes(%s), \nRelationships(%s)" % (self.nodes,
                                                   self.relationships)
    def __bool__(self):
        return len(self.nodes) > 0
    
    def __or__(self, other):
        return Subgraph(set(self.nodes) | set(other.nodes), set(self.relationships) | set(other.relationships))
    
    def __and__(self, other):
        return Subgraph(set(self.nodes) & set(other.nodes), set(self.relationships) & set(other.relationships))

    def __sub__(self, other):
        r = set(self.relationships) - set(other.relationships)
        n = (set(self.nodes) - set(other.nodes)) | set().union(*(set(rel.nodes) for rel in r))
        return Subgraph(n, r)

    def __xor__(self, other):
        r = set(self.relationships) ^ set(other.relationships)
        n = (set(self.nodes) ^ set(other.nodes)) | set().union(*(set(rel.nodes) for rel in r))
        return Subgraph(n, r)

Parameters

Name Type Default Kind
bases - -

Parameter Details

nodes: Optional iterable of node objects to include in the subgraph. Can be None or empty. These nodes will be stored as a frozenset internally.

relationships: Optional iterable of relationship objects connecting nodes. Can be None or empty. The subgraph will automatically include all nodes referenced by these relationships, even if not explicitly provided in the nodes parameter.

graph: Optional reference to a parent graph object that this subgraph belongs to. Used for maintaining context and binding state.

Return Value

Instantiation returns a Subgraph object containing the specified nodes and relationships. The nodes property returns a mutable set of nodes, relationships property returns a mutable set of relationships, and graph property returns the parent graph reference. The unbind() method returns a new unbound Subgraph copy. Set operations (__or__, __and__, __sub__, __xor__) return new Subgraph instances.

Class Interface

Methods

__init__(nodes=None, relationships=None, graph=None)

Purpose: Initialize a Subgraph with optional nodes, relationships, and parent graph reference

Parameters:

  • nodes: Optional iterable of node objects
  • relationships: Optional iterable of relationship objects
  • graph: Optional parent graph reference

Returns: None (constructor)

@property nodes(self) -> set property

Purpose: Get a mutable set of all nodes in the subgraph

Returns: Set containing all node objects in the subgraph

@property relationships(self) -> set property

Purpose: Get a mutable set of all relationships in the subgraph

Returns: Set containing all relationship objects in the subgraph

@property graph(self) property

Purpose: Get the parent graph reference

Returns: The parent graph object or None if unbound

@graph.setter graph(self, graph) property

Purpose: Set the parent graph reference

Parameters:

  • graph: The parent graph object to bind to

Returns: None

unbind(self) -> Subgraph

Purpose: Create an unbound copy of the subgraph with unbound nodes and relationships

Returns: A new Subgraph instance with unbound copies of all nodes and relationships

__str__(self) -> str

Purpose: Return string representation of the subgraph

Returns: String showing nodes and relationships

__repr__(self) -> str

Purpose: Return detailed string representation of the subgraph

Returns: String showing nodes and relationships

__bool__(self) -> bool

Purpose: Check if subgraph contains any nodes

Returns: True if subgraph has nodes, False otherwise

__or__(self, other: Subgraph) -> Subgraph

Purpose: Perform union operation with another subgraph

Parameters:

  • other: Another Subgraph instance to union with

Returns: New Subgraph containing union of nodes and relationships

__and__(self, other: Subgraph) -> Subgraph

Purpose: Perform intersection operation with another subgraph

Parameters:

  • other: Another Subgraph instance to intersect with

Returns: New Subgraph containing intersection of nodes and relationships

__sub__(self, other: Subgraph) -> Subgraph

Purpose: Perform difference operation with another subgraph

Parameters:

  • other: Another Subgraph instance to subtract

Returns: New Subgraph containing elements in self but not in other, preserving nodes connected by remaining relationships

__xor__(self, other: Subgraph) -> Subgraph

Purpose: Perform symmetric difference operation with another subgraph

Parameters:

  • other: Another Subgraph instance for symmetric difference

Returns: New Subgraph containing elements in either subgraph but not both, preserving nodes connected by remaining relationships

Attributes

Name Type Description Scope
_graph object or None Private attribute storing reference to the parent graph object instance
_nodes frozenset Private immutable set storing all node objects in the subgraph instance
_relationships frozenset Private immutable set storing all relationship objects in the subgraph instance

Dependencies

  • uuid
  • itertools

Required Imports

from uuid import uuid4
from itertools import chain

Usage Example

# Assuming Node and Relationship classes are available
from itertools import chain

# Create nodes
node1 = Node('Person', name='Alice', UID='uid1')
node2 = Node('Person', name='Bob', UID='uid2')

# Create a relationship
rel = Relationship(node1, 'KNOWS', node2)

# Create subgraph with nodes and relationships
subgraph1 = Subgraph(nodes=[node1, node2], relationships=[rel])

# Create another subgraph
node3 = Node('Person', name='Charlie', UID='uid3')
subgraph2 = Subgraph(nodes=[node3])

# Combine subgraphs using union
combined = subgraph1 | subgraph2

# Get intersection
common = subgraph1 & subgraph2

# Access nodes and relationships
all_nodes = combined.nodes
all_rels = combined.relationships

# Unbind from graph
unbound_copy = subgraph1.unbind()

# Check if subgraph has nodes
if subgraph1:
    print('Subgraph has nodes')

Best Practices

  • Nodes and relationships are stored as frozensets internally for immutability, but exposed as mutable sets through properties
  • When creating a Subgraph with relationships, you don't need to explicitly provide the connected nodes - they are automatically extracted
  • The unbind() method creates a deep copy with unbound nodes and relationships, useful for detaching from a parent graph
  • Set operations (|, &, -, ^) create new Subgraph instances rather than modifying existing ones
  • The graph property can be set after instantiation to bind the subgraph to a parent graph
  • Boolean evaluation returns True if the subgraph contains any nodes, False otherwise
  • Nodes must have a 'UID' attribute for the unbind() method to work correctly
  • The unbind() method assumes relationships have start_node, end_node, labels, and relationship attributes

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class Graph 59.5% similar

    A Graph class that provides an interface for interacting with a Neo4j graph database, supporting CRUD operations on nodes and relationships through Cypher queries.

    From: /tf/active/vicechatdev/neo4j_driver/neo4j_driver.py
  • class Relationship 58.0% similar

    A class representing a graph relationship between two nodes, wrapping a _Relationship object with start and end Node objects.

    From: /tf/active/vicechatdev/neo4j_driver/neo4j_objects.py
  • class _Relationship 56.1% similar

    A class representing a graph relationship (edge) with labels, properties, and an optional element ID, inheriting from PropertyDict to manage key-value properties.

    From: /tf/active/vicechatdev/neo4j_driver/neo4j_objects.py
  • class Node 53.0% similar

    A Node class representing a graph node with labels and properties, designed to work with Neo4j graph databases. It extends PropertyDict to manage node properties and provides methods for label management and graph synchronization.

    From: /tf/active/vicechatdev/neo4j_driver/neo4j_objects.py
  • class Neo4jManager 44.7% similar

    A manager class that provides a high-level interface for interacting with Neo4j graph databases, handling connections, queries, node creation, and relationship management.

    From: /tf/active/vicechatdev/QA_updater/knowledge_store/neo4j_manager.py
← Back to Browse