Skip to content

Commit 7f4339a

Browse files
committed
encode node, edge and path objects
1 parent 8fbcb11 commit 7f4339a

File tree

4 files changed

+126
-36
lines changed

4 files changed

+126
-36
lines changed

code_graph/entities/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# __init__.py
22

3-
__all__ = ['File', 'Function', 'Argument', 'Class', 'Struct']
4-
53
from .file import File
64
from .cls import Class
75
from .struct import Struct
86
from .function import Function
97
from .argument import Argument
8+
from .entity_encoder import *
109

code_graph/entities/entity_encoder.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from falkordb import Node, Edge, Path
2+
3+
def encode_node(n: Node) -> dict:
4+
n.labels.remove('Searchable')
5+
return vars(n)
6+
7+
def encode_edge(e: Edge) -> dict:
8+
return vars(e)
9+
10+
def encode_path(p: Path) -> dict:
11+
return {
12+
'nodes': [encode_node(n) for n in p.nodes()],
13+
'edges': [encode_edge(e) for e in p.edges()]
14+
}
15+
16+
def encode_graph_entity(e) -> dict:
17+
if isinstance(e, Node):
18+
return encode_node(e)
19+
elif isinstance(e, Edge):
20+
return encode_edge(e)
21+
elif isinstance(e, Path):
22+
return encode_path(e)
23+
else:
24+
raise Exception("Unable to encode graph entity, unknown graph entity type: {type(e)}")
25+

code_graph/graph.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import time
22
from .entities import *
33
from typing import List, Optional
4-
from falkordb import FalkorDB, Node, QueryResult
4+
from falkordb import FalkorDB, Path, Node, QueryResult
55

66
FALKORDB_HOST = "localhost"
77
FALKORDB_PORT = 6379
@@ -86,6 +86,29 @@ def delete(self) -> None:
8686
self.g.delete()
8787

8888

89+
def get_sub_graph(self, l: int) -> dict:
90+
91+
q = """MATCH (src)
92+
OPTIONAL MATCH (src)-[e]->(dest)
93+
RETURN src, e, dest
94+
LIMIT $limit"""
95+
96+
sub_graph = {'nodes': [], 'edges': [] }
97+
98+
result_set = self.g.query(q, {'limit': l}).result_set
99+
for row in result_set:
100+
src = row[0]
101+
e = row[1]
102+
dest = row[2]
103+
104+
sub_graph['nodes'].append(encode_node(src))
105+
106+
if e is not None:
107+
sub_graph['edges'].append(encode_edge(e))
108+
sub_graph['nodes'].append(encode_node(dest))
109+
110+
return sub_graph
111+
89112
def add_class(self, c: Class) -> None:
90113
"""
91114
Adds a class node to the graph database.
@@ -554,3 +577,38 @@ def rerun_query(self, q: str, params: dict) -> QueryResult:
554577

555578
return self.g.query(q, params)
556579

580+
def find_paths(self, src: int, dest: int) -> List[Path]:
581+
"""
582+
Find all paths between the source (src) and destination (dest) nodes.
583+
584+
Args:
585+
src (int): The ID of the source node.
586+
dest (int): The ID of the destination node.
587+
588+
Returns:
589+
List[Optional[Path]]: A list of paths found between the src and dest nodes.
590+
Returns an empty list if no paths are found.
591+
592+
Raises:
593+
Exception: If the query fails or the graph database returns an error.
594+
"""
595+
596+
# Define the query to match paths between src and dest nodes.
597+
q = """MATCH (src), (dest)
598+
WHERE ID(src) = $src_id AND ID(dest) = $dest_id
599+
WITH src, dest
600+
MATCH p = (src)-[:CALLS*]->(dest)
601+
RETURN p
602+
"""
603+
604+
# Perform the query with the source and destination node IDs.
605+
result_set = self.g.query(q, {'src_id': src, 'dest_id': dest}).result_set
606+
607+
paths = []
608+
609+
# Extract paths from the query result set.
610+
for row in result_set:
611+
paths.append(row[0])
612+
613+
return paths
614+

main.py

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -34,42 +34,15 @@ def extract_org_name_from_url(url: str) -> Optional[tuple[str, str]]:
3434

3535
@app.route('/graph_entities', methods=['GET'])
3636
def graph_entities():
37-
# Access the 'graph_id' parameter from the GET request
38-
graph_id = request.args.get('graph_id')
39-
40-
# Connect to FalkorDB
41-
db = FalkorDB(host=FALKORDB_HOST, port=FALKORDB_PORT,
42-
username=FALKORDB_USERNAME, password=FALKORDB_PASSWORD)
37+
# Access the 'repo' parameter from the GET request
38+
repo = request.args.get('repo')
4339

44-
# Select graph
45-
g = db.select_graph(graph_id)
46-
47-
query = """MATCH (src)
48-
OPTIONAL MATCH (src)-[e]->(dest)
49-
RETURN src, e, dest
50-
LIMIT 100"""
51-
52-
data = []
53-
res = g.query(query).result_set
54-
for row in res:
55-
src = row[0]
56-
e = row[1]
57-
dest = row[2]
58-
59-
data.append({'data': {'id': src.id,
60-
'label': src.labels[0]} })
61-
62-
if e is not None:
63-
data.append({'data': {'id': dest.id,
64-
'label': dest.labels[0]} })
65-
data.append({'data': {'source': src.id, 'target': dest.id, 'relation': e.relation} })
40+
g = Graph(repo, host=FALKORDB_HOST, port=FALKORDB_PORT,
41+
username=FALKORDB_USERNAME, password=FALKORDB_PASSWORD)
6642

67-
# [
68-
# { data: { id: 'e' } },
69-
# { data: { source: 'a', target: 'b' } }
70-
# ]
43+
sub_graph = g.get_sub_graph(100)
7144

72-
return jsonify(data), 200
45+
return jsonify(sub_graph), 200
7346

7447
@app.route('/get_neighbors', methods=['GET'])
7548
def get_neighbors():
@@ -325,6 +298,41 @@ def process_list_commits():
325298

326299
return jsonify(response), 200
327300

301+
@app.route('/find_paths', methods=['POST'])
302+
def find_paths():
303+
# Get JSON data from the request
304+
data = request.get_json()
305+
306+
# name of repository
307+
repo = data.get('repo')
308+
if repo is None:
309+
return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400
310+
311+
# source ID
312+
src = data.get('src')
313+
if src is None:
314+
return jsonify({'status': f'Missing mandatory parameter "src"'}), 400
315+
316+
# dest ID
317+
dest = data.get('dest')
318+
if dest is None:
319+
return jsonify({'status': f'Missing mandatory parameter "dest"'}), 400
320+
321+
# Get JSON data from the request
322+
g = Graph(repo, host=FALKORDB_HOST, port=FALKORDB_PORT,
323+
username=FALKORDB_USERNAME, password=FALKORDB_PASSWORD)
324+
325+
paths = g.find_paths(src, dest)
326+
327+
# Create a response
328+
response = {
329+
'status': 'success',
330+
'paths': paths
331+
}
332+
333+
return jsonify(response), 200
334+
335+
328336
if __name__ == '__main__':
329337
app.run(debug=True)
330338

0 commit comments

Comments
 (0)