class ResultWrapper
ResultWrapper is a tuple subclass that wraps Cypher query results from Neo4j, providing methods to convert results into various formats including Node/Relationship objects, DataFrames, dictionaries, and Subgraphs.
/tf/active/vicechatdev/neo4j_driver/neo4j_driver.py
8 - 90
moderate
Purpose
This class serves as a wrapper around Neo4j Cypher query results, extending the built-in tuple class to provide convenient methods for transforming query results into different data structures. It handles conversion of raw Neo4j graph objects (nodes, relationships, paths) into higher-level Python objects and data structures like Pandas DataFrames, lists of dictionaries, and Subgraph objects. The class maintains a reference to the parent graph for proper object instantiation.
Source Code
class ResultWrapper(tuple):
"""
The ResultWrapper class is a custom class that extends the built-in tuple class. It is used to wrap the results of Cypher queries and provide additional methods for working with the results.
The methods include evaluating the results to return Node and Relationship objects, converting the results to a Pandas DataFrame, returning the data as a list of dictionaries,
and returning the results as a Subgraph object.
"""
def __init__(self, *args, graph=None):
tuple.__init__(self)
self._graph=graph
def evaluate(self):
if not self:
return None
if isinstance(self[0].value(), neo4j.graph.Node):
if len(self) > 1:
warnings.warn("Query matched multiple nodes, but .evaluate only processes a single node. Either use .subgraph or call `RETURN COLLECT(nodes)`", stacklevel=2)
return Node._from_neo4j_node(self[0].value(), graph=self._graph)
elif isinstance(self[0].value(), list) and len(self[0].value()) > 0 and isinstance(self[0].value()[0], neo4j.graph.Node):
return [Node._from_neo4j_node(i, graph=self._graph) for i in self[0].value()]
elif isinstance(self[0].value(), list) and len(self[0].value()) > 0 and isinstance(self[0].value()[0], neo4j.graph.Relationship):
return [Relationship._from_neo4j_node(i, graph=self._graph) for i in self[0].value()]
elif isinstance(self[0].value(), neo4j.graph.Relationship):
return Relationship._from_neo4j_node(self[0].value(), graph=self._graph)
return self[0].value()
def to_data_frame(self):
import pandas as pd
try:
if isinstance(self.values[0], Node):
return pd.DataFrame([dict(i) for i in self.values])
return pd.DataFrame(self.values, columns=self.keys)
except:
return pd.DataFrame()
def data(self):
if self.values is None:
return []
data=[]
for values in self.values:
if isinstance(values, Node):
d=dict(values)
else:
d= dict(zip(self.keys, values))
data.append(d)
return data
def to_ndarray(self):
warnings.warn("This function was only implemented to return lists and does not actually return an ndarray. Please return collections and call .evaluate instead", stacklevel=5)
return self.values
def to_subgraph(self):
if not self:
return Subgraph(graph=self._graph)
if isinstance(self[0].values(), neo4j.graph.Path) or isinstance(self[0].values()[0], neo4j.graph.Path):
relationships=[]
for path in self:
for relationship in path.value():
relationships.append(relationship)
subgraph = Subgraph(relationships=[Relationship._from_neo4j_node(i) for i in relationships], graph=self)
elif isinstance(self[0].values()[0], neo4j.graph.Node):
subgraph = Subgraph(nodes=self.values, graph=self._graph)
elif isinstance(self[0].values()[0], neo4j.graph.Relationship):
subgraph = Subgraph(relationships=self.values, graph=self._graph)
else:
raise TypeError(".to_subgraph only works on neo4j path, node and relationship objects.")
return subgraph
@property
def values(self):
if len(self) == 0:
return None
if isinstance(self[0].value(), neo4j.graph.Node):
return [Node._from_neo4j_node(i.value(), graph=self._graph) for i in self]
elif isinstance(self[0].value(), neo4j.graph.Relationship):
return [Relationship._from_neo4j_node(i.value(), graph=self._graph) for i in self]
return [i.values() for i in self]
@property
def keys(self):
keys = []
keys.extend(j for i in self for j in i.keys() if not j in keys)
return keys
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
tuple | - |
Parameter Details
*args: Variable positional arguments passed to the tuple constructor, typically containing Neo4j query result records
graph: Optional reference to the parent Graph object that executed the query. Used to maintain graph context when creating Node and Relationship objects from Neo4j results. Defaults to None.
Return Value
Instantiation returns a ResultWrapper object that behaves like a tuple but with additional methods. Key method returns: evaluate() returns Node, Relationship objects, or lists thereof, or primitive values; to_data_frame() returns a Pandas DataFrame; data() returns a list of dictionaries; to_subgraph() returns a Subgraph object; values property returns a list of converted values; keys property returns a list of unique keys from all records.
Class Interface
Methods
__init__(self, *args, graph=None)
Purpose: Initialize the ResultWrapper with query results and optional graph reference
Parameters:
*args: Variable positional arguments containing Neo4j query result recordsgraph: Optional reference to the parent Graph object for maintaining context
Returns: None (constructor)
evaluate(self) -> Node | Relationship | list | Any | None
Purpose: Evaluate the first result and convert it to appropriate Python objects (Node, Relationship, or primitive types)
Returns: Returns None if empty; Node object for single node results; Relationship object for single relationship results; list of Node objects for node collections; list of Relationship objects for relationship collections; or the raw value for other types. Warns if multiple nodes matched but only processes first.
to_data_frame(self) -> pd.DataFrame
Purpose: Convert the query results to a Pandas DataFrame
Returns: Pandas DataFrame containing the results. If values are Node objects, converts them to dictionaries. Otherwise uses keys and values. Returns empty DataFrame on error.
data(self) -> list[dict]
Purpose: Convert query results to a list of dictionaries
Returns: List of dictionaries where each dictionary represents a result record. Node objects are converted to dicts, other values are zipped with keys. Returns empty list if values is None.
to_ndarray(self) -> list
Purpose: Deprecated method that returns values as a list (not an actual ndarray)
Returns: Returns the values property (a list). Emits deprecation warning recommending use of collections and evaluate() instead.
to_subgraph(self) -> Subgraph
Purpose: Convert query results to a Subgraph object containing nodes and/or relationships
Returns: Subgraph object constructed from the results. Handles Path, Node, and Relationship types. Returns empty Subgraph if ResultWrapper is empty. Raises TypeError for unsupported types.
values(self) -> list | None
property
Purpose: Property that returns the values from all result records, converting Neo4j objects to Python objects
Returns: None if empty; list of Node objects if results contain nodes; list of Relationship objects if results contain relationships; otherwise list of raw values from each record.
keys(self) -> list[str]
property
Purpose: Property that returns all unique keys from the result records
Returns: List of unique key names (strings) from all records in the results, preserving order of first appearance.
Attributes
| Name | Type | Description | Scope |
|---|---|---|---|
_graph |
Graph | None | Private attribute storing reference to the parent Graph object, used for maintaining context when creating Node and Relationship objects | instance |
Dependencies
neo4jpandaswarningsneo4j_objects
Required Imports
import neo4j
import warnings
from neo4j_objects import Node, Relationship, Subgraph
Conditional/Optional Imports
These imports are only needed under specific conditions:
import pandas as pd
Condition: only when calling to_data_frame() method
Required (conditional)Usage Example
# Assuming you have a Neo4j graph connection and query results
from neo4j import GraphDatabase
from neo4j_objects import Node, Relationship, Subgraph
# Execute a query that returns results
driver = GraphDatabase.driver('bolt://localhost:7687', auth=('neo4j', 'password'))
with driver.session() as session:
raw_results = session.run('MATCH (n:Person) RETURN n LIMIT 5')
# Wrap results
results = ResultWrapper(*raw_results, graph=my_graph)
# Get single node/relationship
node = results.evaluate()
# Convert to DataFrame
df = results.to_data_frame()
# Get as list of dictionaries
data_list = results.data()
# Convert to Subgraph
subgraph = results.to_subgraph()
# Access values and keys
values = results.values
keys = results.keys
Best Practices
- Always pass the graph parameter when instantiating to maintain proper graph context for Node and Relationship objects
- Use evaluate() for single-result queries; it warns if multiple nodes are matched but only processes the first
- Check if ResultWrapper is empty before calling methods to avoid errors
- Use to_subgraph() only with Neo4j path, node, or relationship objects; other types will raise TypeError
- Be aware that to_ndarray() is deprecated and only returns lists, not actual ndarrays
- The class is immutable (tuple subclass), so results cannot be modified after creation
- When working with collections of nodes/relationships, use COLLECT() in Cypher queries for proper handling with evaluate()
- The values property returns None if the ResultWrapper is empty, so check for None before iterating
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
class IterationResult 54.0% similar
-
function run_query_v2 52.6% similar
-
class SqlGenerationResult 50.8% similar
-
class Graph 50.6% similar
-
class AnalysisResult_v1 49.4% similar