Skip to content

Commit

Permalink
Fix incorrect visualizations of Gremlin results returned by valueMap (#…
Browse files Browse the repository at this point in the history
…165)

* Fix Gremlin visualization bug

* Update Changelog

* Another Changelog update

Co-authored-by: Michael Chin <[email protected]>
  • Loading branch information
michaelnchin and michaelnchin authored Jul 30, 2021
1 parent 687faf9 commit 0a0c3a4
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 33 deletions.
6 changes: 6 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ Starting with v1.31.6, this file will contain a record of major features and upd

## Upcoming

- Add new Knowledge Graph use case notebook for openCypher usage ([Link to PR](https://github.com/aws/graph-notebook/pull/161))
- Fixed incorrect visualizations of some Gremlin results returned by valueMap ([Link to PR](https://github.com/aws/graph-notebook/pull/165))
- Fixed error with Gremlin visualizer incorrectly identifying some query results as elementMaps ([Link to PR](https://github.com/aws/graph-notebook/pull/158))
- Pin RDFLib version in README ([Link to PR](https://github.com/aws/graph-notebook/pull/162))
- Fixed inconsistent node tooltips in openCypher visualizations ([Link to PR](https://github.com/aws/graph-notebook/pull/163))

## Release 3.0.1 (July 28, 2021)

**openCypher Support**:
Expand Down
83 changes: 50 additions & 33 deletions src/graph_notebook/network/gremlin/GremlinNetwork.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,41 +240,23 @@ def add_results(self, results):

for i in range(len(path)):
if isinstance(path[i], dict):
self.insert_elementmap(path[i])
else:
if i == 0:
self.add_vertex(path[i])
continue

if type(path[i]) is Edge:
edge = path[i]
path_left = get_id(path[i - 1])
path_right = get_id(path[i + 1])

# If the edge is an object type but its vertices aren't, then the ID contained
# in the edge won't be the same as the ids used to store those two vertices.
# For example, g.V().inE().outV().path().by(valueMap()).by().by(valueMap(true)
# will yield a V, E, V pattern where the first vertex is a dict without T.id, the edge
# will be an Edge object, and the second vertex will be a dict with T.id.
if edge.outV.id == path_left or edge.inV.id == path_right:
from_id = path_left
to_id = path_right
self.add_path_edge(path[i], from_id, to_id)
elif edge.inV.id == path_left or edge.outV.id == path_right:
from_id = path_right
to_id = path_left
self.add_path_edge(path[i], from_id, to_id)
else:
from_id = path_left
to_id = path_right
self.add_blank_edge(from_id, to_id, edge.id, label=edge.label)
continue
is_elementmap = False
for prop, value in path[i].items():
if prop not in [T.id, T.label] and isinstance(value, str):
is_elementmap = True
break
elif isinstance(value, dict):
is_elementmap = True
break
elif isinstance(value, list):
break
if is_elementmap:
self.insert_elementmap(path[i])
else:
from_id = get_id(path[i - 1])
self.insert_path_element(path, i)
else:
self.insert_path_element(path, i)

self.add_vertex(path[i])
if type(path[i - 1]) is not Edge:
self.add_blank_edge(from_id, get_id(path[i]))
elif isinstance(path, dict) and T.id in path.keys() and T.label in path.keys():
self.insert_elementmap(path)
else:
Expand Down Expand Up @@ -452,6 +434,41 @@ def add_blank_edge(self, from_id, to_id, edge_id=None, undirected=True, label=''
edge_data = UNDIRECTED_EDGE if undirected else {}
self.add_edge(from_id, to_id, edge_id, label, edge_data)

def insert_path_element(self, path, i):
if i == 0:
self.add_vertex(path[i])
return

if type(path[i]) is Edge:
edge = path[i]
path_left = get_id(path[i - 1])
path_right = get_id(path[i + 1])

# If the edge is an object type but its vertices aren't, then the ID contained
# in the edge won't be the same as the ids used to store those two vertices.
# For example, g.V().inE().outV().path().by(valueMap()).by().by(valueMap(true)
# will yield a V, E, V pattern where the first vertex is a dict without T.id, the edge
# will be an Edge object, and the second vertex will be a dict with T.id.
if edge.outV.id == path_left or edge.inV.id == path_right:
from_id = path_left
to_id = path_right
self.add_path_edge(path[i], from_id, to_id)
elif edge.inV.id == path_left or edge.outV.id == path_right:
from_id = path_right
to_id = path_left
self.add_path_edge(path[i], from_id, to_id)
else:
from_id = path_left
to_id = path_right
self.add_blank_edge(from_id, to_id, edge.id, label=edge.label)
return
else:
from_id = get_id(path[i - 1])

self.add_vertex(path[i])
if type(path[i - 1]) is not Edge:
self.add_blank_edge(from_id, get_id(path[i]))

def insert_elementmap(self, e_map):
"""
Add a vertex or edge that has been returned by an elementMap query step.
Expand Down
57 changes: 57 additions & 0 deletions test/unit/network/gremlin/test_gremlin_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -1523,6 +1523,63 @@ def test_add_results_as_path_containing_elementmaps(self):
self.assertEqual(inv_data['properties'], in_vertex)
self.assertEqual(edge_data, edge_expected)

def test_add_results_as_path_containing_valuemaps(self):

out_vertex = {
'country': ['US'],
'code': ['SAF'],
'longest': [8366],
'city': ['Santa Fe'],
'lon': [-106.088996887],
'type': ['airport'],
T.id: '44', 'elev': [6348],
T.label: 'airport',
'icao': ['KSAF'],
'runways': [3],
'region': ['US-NM'],
'lat': [35.617099762],
'desc': ['Santa Fe']
}

in_vertex = {
'country': ['US'],
'code': ['DFW'],
'longest': [13401],
'city': ['Dallas'],
'lon': [-97.0380020141602],
'type': ['airport'],
T.id: '8',
'elev': [607],
T.label: 'airport',
'icao': ['KDFW'],
'runways': [7],
'region': ['US-TX'],
'lat': [32.896800994873],
'desc': ['Dallas/Fort Worth International Airport']
}

edge_value_expected = {
'arrows': {
'to': {
'enabled': False
}
},
'label': ''
}

path = Path([], [out_vertex, in_vertex])
gn = GremlinNetwork()
gn.add_results([path])
edge_data = gn.graph.get_edge_data('44', '8')
for prop, value in edge_data.items():
edge_data_value = value
break
outv_data = gn.graph.nodes.get('44')
inv_data = gn.graph.nodes.get('8')
self.assertEqual(outv_data['properties'], out_vertex)
self.assertEqual(inv_data['properties'], in_vertex)
self.assertEqual(edge_data_value, edge_value_expected)


if __name__ == '__main__':
unittest.main()

0 comments on commit 0a0c3a4

Please sign in to comment.