Skip to content

Staging #25

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

Merged
merged 13 commits into from
Nov 24, 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
3 changes: 0 additions & 3 deletions .env

This file was deleted.

18 changes: 9 additions & 9 deletions api/graph.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import time
from .entities import *
from typing import Dict, List, Optional, Tuple
from typing import Dict, Optional, List, Tuple
from falkordb import FalkorDB, Path, Node, QueryResult

# Configure the logger
Expand Down Expand Up @@ -194,12 +194,12 @@ def get_sub_graph(self, l: int) -> dict:
return sub_graph


def get_neighbors(self, node_id: int, rel: Optional[str] = None, lbl: Optional[str] = None) -> Dict[str, List[dict]]:
def get_neighbors(self, node_ids: List[int], rel: Optional[str] = None, lbl: Optional[str] = None) -> Dict[str, List[dict]]:
"""
Fetch the neighbors of a given node in the graph based on relationship type and/or label.
Fetch the neighbors of a given nodes in the graph based on relationship type and/or label.

Args:
node_id (int): The ID of the source node.
node_ids (List[int]): The IDs of the source nodes.
rel (str, optional): The type of relationship to filter by. Defaults to None.
lbl (str, optional): The label of the destination node to filter by. Defaults to None.

Expand All @@ -208,8 +208,8 @@ def get_neighbors(self, node_id: int, rel: Optional[str] = None, lbl: Optional[s
"""

# Validate inputs
if not isinstance(node_id, int):
raise ValueError("node_id must be an integer")
if not all(isinstance(node_id, int) for node_id in node_ids):
raise ValueError("node_ids must be an integer list")

# Build relationship and label query parts
rel_query = f":{rel}" if rel else ""
Expand All @@ -218,7 +218,7 @@ def get_neighbors(self, node_id: int, rel: Optional[str] = None, lbl: Optional[s
# Parameterized Cypher query to find neighbors
query = f"""
MATCH (n)-[e{rel_query}]->(dest{lbl_query})
WHERE ID(n) = $node_id
WHERE ID(n) IN $node_ids
RETURN e, dest
"""

Expand All @@ -227,7 +227,7 @@ def get_neighbors(self, node_id: int, rel: Optional[str] = None, lbl: Optional[s

try:
# Execute the graph query with node_id parameter
result_set = self._query(query, {'node_id': node_id}).result_set
result_set = self._query(query, {'node_ids': node_ids}).result_set

# Iterate over the result set and process nodes and edges
for edge, destination_node in result_set:
Expand All @@ -237,7 +237,7 @@ def get_neighbors(self, node_id: int, rel: Optional[str] = None, lbl: Optional[s
return neighbors

except Exception as e:
logging.error(f"Error fetching neighbors for node {node_id}: {e}")
logging.error(f"Error fetching neighbors for node {node_ids}: {e}")
return {'nodes': [], 'edges': []}


Expand Down
33 changes: 14 additions & 19 deletions api/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,51 +79,47 @@ def graph_entities():
return jsonify({"status": "Internal server error"}), 500


@app.route('/get_neighbors', methods=['GET'])
@app.route('/get_neighbors', methods=['POST'])
@token_required # Apply token authentication decorator
def get_neighbors():
"""
Endpoint to get neighbors of a specific node in the graph.
Expects 'repo' and 'node_id' as query parameters.
Endpoint to get neighbors of a nodes list in the graph.
Expects 'repo' and 'node_ids' as body parameters.

Returns:
JSON response containing neighbors or error messages.
"""

# Get JSON data from the request
data = request.get_json()

# Get query parameters
repo = request.args.get('repo')
node_id = request.args.get('node_id')
repo = data.get('repo')
node_ids = data.get('node_ids')

# Validate 'repo' parameter
if not repo:
logging.error("Repository name is missing in the request.")
return jsonify({"status": "Repository name is required."}), 400

# Validate 'node_id' parameter
if not node_id:
logging.error("Node ID is missing in the request.")
return jsonify({"status": "Node ID is required."}), 400
# Validate 'node_ids' parameter
if not node_ids:
logging.error("Node IDs is missing in the request.")
return jsonify({"status": "Node IDs is required."}), 400

# Validate repo exists
if not graph_exists(repo):
logging.error(f"Missing project {repo}")
return jsonify({"status": f"Missing project {repo}"}), 400

# Try converting node_id to an integer
try:
node_id = int(node_id)
except ValueError:
logging.error(f"Invalid node ID: {node_id}. It must be an integer.")
return jsonify({"status": "Invalid node ID. It must be an integer."}), 400

# Initialize the graph with the provided repository
g = Graph(repo)

# Fetch the neighbors of the specified node
neighbors = g.get_neighbors(node_id)
neighbors = g.get_neighbors(node_ids)

# Log and return the neighbors
logging.info(f"Successfully retrieved neighbors for node ID {node_id} in repo '{repo}'.")
logging.info(f"Successfully retrieved neighbors for node IDs {node_ids} in repo '{repo}'.")

response = {
'status': 'success',
Expand Down Expand Up @@ -170,7 +166,6 @@ def auto_complete():

return jsonify(response), 200


@app.route('/list_repos', methods=['GET'])
@token_required # Apply token authentication decorator
def list_repos():
Expand Down
Loading