Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional autocomplete of relationships #3

Merged
merged 5 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ The main class `Neo4jGraphWidget` provides the following API:
- `**kwargs`: Additional parameters that should be passed to the cypher query (e.g., see
the [selection example](https://github.com/yWorks/yfiles-jupyter-graphs-for-neo4j/blob/main/examples/selection_example.ipynb)).

The default behavior is to only show the nodes and relationships returned by the cypher query.
This can be changed to autocomplete relationships like in neo4j browser:
- `set_autocomplete_relationships(autocomplete_relationships)`: Sets whether to autocomplete relationships in the graph or not.

The cypher queries are executed by the provided Neo4j driver. If you have not specified a driver when instantiating the
class, you can set
a driver afterward:
Expand Down
47 changes: 46 additions & 1 deletion src/yfiles_jupyter_graphs_for_neo4j/Yfiles_Neo4j_Graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ class Neo4jGraphWidget:
_widget = GraphWidget()

def __init__(self, driver=None, widget_layout=None,
overview_enabled=None, context_start_with='About', license=None):
overview_enabled=None, context_start_with='About', license=None,
autocomplete_relationships=False):
if driver is not None:
self._driver = driver
self._session = driver.session()
self._license = license
self._overview = overview_enabled
self._layout = widget_layout
self._context_start_with = context_start_with
self.set_autocomplete_relationships(autocomplete_relationships)

def set_driver(self, driver):
"""
Expand All @@ -44,13 +46,56 @@ def get_driver(self):
"""
return self._driver

def set_autocomplete_relationships(self, autocomplete_relationships):
"""
Sets the flag to enable or disable autocomplete for relationships.
When autocomplete is enabled, relationships are automatically completed in the graph,
similar to the behavior in Neo4j Browser.
This can be set to True/False to enable or disable for all relationships,
or a single relationship type or a list of relationship types to enable for specific relationships.
:param autocomplete_relationships: bool | str | list[str]
"""
if not isinstance(autocomplete_relationships, (bool, str, list)):
raise ValueError("autocomplete_relationships must be a bool, a string, or a list of strings")
if isinstance(autocomplete_relationships, str):
self._autocomplete_relationships = [autocomplete_relationships]
else:
self._autocomplete_relationships = autocomplete_relationships

def _is_autocomplete_enabled(self):
if isinstance(self._autocomplete_relationships, bool):
return self._autocomplete_relationships
return len(self._autocomplete_relationships) > 0

def _get_relationship_types_expression(self):
if isinstance(self._autocomplete_relationships, list) and len(self._autocomplete_relationships) > 0:
return "AND type(rel) IN $relationship_types"
return ""

def show_cypher(self, cypher, **kwargs):
"""
main function
:param cypher: str, Send a data query to the neo4j database
**kwargs: variable declarations usable in cypher
"""
if self._driver is not None:
if self._is_autocomplete_enabled():
nodes = self._session.run(cypher, **kwargs).graph().nodes
node_ids = [node.element_id for node in nodes]
reltypes_expr = self._get_relationship_types_expression()
cypher = f"""
MATCH (n) WHERE elementId(n) IN $node_ids
RETURN n as start, NULL as rel, NULL as end
UNION ALL
MATCH (n)-[rel]-(m)
WHERE elementId(n) IN $node_ids
AND elementId(m) IN $node_ids
{reltypes_expr}
RETURN n as start, rel, m as end
"""
kwargs = {"node_ids": node_ids}
if reltypes_expr:
kwargs["relationship_types"] = self._autocomplete_relationships
widget = GraphWidget(overview_enabled=self._overview, context_start_with=self._context_start_with,
widget_layout=self._layout, license=self._license,
graph=self._session.run(cypher, **kwargs).graph())
Expand Down