feat(geo): filter clustered nodes by product/hub/supplier
All checks were successful
Build Docker Image / build (push) Successful in 2m42s
All checks were successful
Build Docker Image / build (push) Successful in 2m42s
This commit is contained in:
@@ -17,7 +17,18 @@ ZOOM_TO_RES = {
|
||||
}
|
||||
|
||||
|
||||
def _fetch_nodes(db, west, south, east, north, transport_type=None, node_type=None):
|
||||
def _fetch_nodes(
|
||||
db,
|
||||
west,
|
||||
south,
|
||||
east,
|
||||
north,
|
||||
transport_type=None,
|
||||
node_type=None,
|
||||
product_uuid=None,
|
||||
hub_uuid=None,
|
||||
supplier_uuid=None,
|
||||
):
|
||||
"""Fetch nodes from database for a bounding box.
|
||||
|
||||
Args:
|
||||
@@ -31,6 +42,9 @@ def _fetch_nodes(db, west, south, east, north, transport_type=None, node_type=No
|
||||
'south': south,
|
||||
'east': east,
|
||||
'north': north,
|
||||
'product_uuid': product_uuid,
|
||||
'hub_uuid': hub_uuid,
|
||||
'supplier_uuid': supplier_uuid,
|
||||
}
|
||||
|
||||
# Select AQL query based on node_type
|
||||
@@ -41,6 +55,19 @@ def _fetch_nodes(db, west, south, east, north, transport_type=None, node_type=No
|
||||
FILTER node.latitude != null AND node.longitude != null
|
||||
FILTER node.latitude >= @south AND node.latitude <= @north
|
||||
FILTER node.longitude >= @west AND node.longitude <= @east
|
||||
FILTER @product_uuid == null OR node.product_uuid == @product_uuid
|
||||
FILTER @supplier_uuid == null OR node.supplier_uuid == @supplier_uuid
|
||||
LET has_hub = @hub_uuid == null ? true : LENGTH(
|
||||
FOR edge IN edges
|
||||
FILTER edge.transport_type == 'offer'
|
||||
FILTER (
|
||||
(edge._from == CONCAT('nodes/', node._key) AND edge._to == CONCAT('nodes/', @hub_uuid)) OR
|
||||
(edge._to == CONCAT('nodes/', node._key) AND edge._from == CONCAT('nodes/', @hub_uuid))
|
||||
)
|
||||
LIMIT 1
|
||||
RETURN 1
|
||||
) > 0
|
||||
FILTER has_hub
|
||||
RETURN node
|
||||
"""
|
||||
elif node_type == 'supplier':
|
||||
@@ -49,6 +76,19 @@ def _fetch_nodes(db, west, south, east, north, transport_type=None, node_type=No
|
||||
FOR offer IN nodes
|
||||
FILTER offer.node_type == 'offer'
|
||||
FILTER offer.supplier_uuid != null
|
||||
FILTER @product_uuid == null OR offer.product_uuid == @product_uuid
|
||||
FILTER @supplier_uuid == null OR offer.supplier_uuid == @supplier_uuid
|
||||
LET has_hub = @hub_uuid == null ? true : LENGTH(
|
||||
FOR edge IN edges
|
||||
FILTER edge.transport_type == 'offer'
|
||||
FILTER (
|
||||
(edge._from == CONCAT('nodes/', offer._key) AND edge._to == CONCAT('nodes/', @hub_uuid)) OR
|
||||
(edge._to == CONCAT('nodes/', offer._key) AND edge._from == CONCAT('nodes/', @hub_uuid))
|
||||
)
|
||||
LIMIT 1
|
||||
RETURN 1
|
||||
) > 0
|
||||
FILTER has_hub
|
||||
LET supplier = DOCUMENT(CONCAT('nodes/', offer.supplier_uuid))
|
||||
FILTER supplier != null
|
||||
FILTER supplier.latitude != null AND supplier.longitude != null
|
||||
@@ -74,6 +114,20 @@ def _fetch_nodes(db, west, south, east, north, transport_type=None, node_type=No
|
||||
FILTER node.latitude != null AND node.longitude != null
|
||||
FILTER node.latitude >= @south AND node.latitude <= @north
|
||||
FILTER node.longitude >= @west AND node.longitude <= @east
|
||||
FILTER @hub_uuid == null OR node._key == @hub_uuid
|
||||
LET has_offer = (@product_uuid == null AND @supplier_uuid == null) ? true : LENGTH(
|
||||
FOR edge IN edges
|
||||
FILTER edge.transport_type == 'offer'
|
||||
FILTER edge._from == CONCAT('nodes/', node._key) OR edge._to == CONCAT('nodes/', node._key)
|
||||
LET offer_id = edge._from == CONCAT('nodes/', node._key) ? edge._to : edge._from
|
||||
LET offer = DOCUMENT(offer_id)
|
||||
FILTER offer != null AND offer.node_type == 'offer'
|
||||
FILTER @product_uuid == null OR offer.product_uuid == @product_uuid
|
||||
FILTER @supplier_uuid == null OR offer.supplier_uuid == @supplier_uuid
|
||||
LIMIT 1
|
||||
RETURN 1
|
||||
) > 0
|
||||
FILTER has_offer
|
||||
RETURN node
|
||||
"""
|
||||
|
||||
@@ -97,7 +151,19 @@ def _fetch_nodes(db, west, south, east, north, transport_type=None, node_type=No
|
||||
return nodes
|
||||
|
||||
|
||||
def get_clustered_nodes(db, west, south, east, north, zoom, transport_type=None, node_type=None):
|
||||
def get_clustered_nodes(
|
||||
db,
|
||||
west,
|
||||
south,
|
||||
east,
|
||||
north,
|
||||
zoom,
|
||||
transport_type=None,
|
||||
node_type=None,
|
||||
product_uuid=None,
|
||||
hub_uuid=None,
|
||||
supplier_uuid=None,
|
||||
):
|
||||
"""
|
||||
Get clustered nodes for given bounding box and zoom level.
|
||||
|
||||
@@ -111,7 +177,18 @@ def get_clustered_nodes(db, west, south, east, north, zoom, transport_type=None,
|
||||
node_type: Type of nodes ('logistics', 'offer', 'supplier')
|
||||
"""
|
||||
resolution = ZOOM_TO_RES.get(int(zoom), 5)
|
||||
nodes = _fetch_nodes(db, west, south, east, north, transport_type, node_type)
|
||||
nodes = _fetch_nodes(
|
||||
db,
|
||||
west,
|
||||
south,
|
||||
east,
|
||||
north,
|
||||
transport_type,
|
||||
node_type,
|
||||
product_uuid,
|
||||
hub_uuid,
|
||||
supplier_uuid,
|
||||
)
|
||||
|
||||
if not nodes:
|
||||
return []
|
||||
@@ -157,4 +234,3 @@ def get_clustered_nodes(db, west, south, east, north, zoom, transport_type=None,
|
||||
|
||||
logger.info("Returning %d clusters/points for zoom=%d res=%d", len(results), zoom, resolution)
|
||||
return results
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@ class Query(graphene.ObjectType):
|
||||
zoom=graphene.Int(required=True, description="Map zoom level (0-16)"),
|
||||
transport_type=graphene.String(description="Filter by transport type"),
|
||||
node_type=graphene.String(description="Node type: logistics, offer, supplier"),
|
||||
product_uuid=graphene.String(description="Filter by product UUID"),
|
||||
hub_uuid=graphene.String(description="Filter by hub UUID"),
|
||||
supplier_uuid=graphene.String(description="Filter by supplier UUID"),
|
||||
description="Get clustered nodes for map display (server-side clustering)",
|
||||
)
|
||||
|
||||
@@ -848,10 +851,35 @@ class Query(graphene.ObjectType):
|
||||
|
||||
return None
|
||||
|
||||
def resolve_clustered_nodes(self, info, west, south, east, north, zoom, transport_type=None, node_type=None):
|
||||
def resolve_clustered_nodes(
|
||||
self,
|
||||
info,
|
||||
west,
|
||||
south,
|
||||
east,
|
||||
north,
|
||||
zoom,
|
||||
transport_type=None,
|
||||
node_type=None,
|
||||
product_uuid=None,
|
||||
hub_uuid=None,
|
||||
supplier_uuid=None,
|
||||
):
|
||||
"""Get clustered nodes for map display using server-side SuperCluster."""
|
||||
db = get_db()
|
||||
clusters = get_clustered_nodes(db, west, south, east, north, zoom, transport_type, node_type)
|
||||
clusters = get_clustered_nodes(
|
||||
db,
|
||||
west,
|
||||
south,
|
||||
east,
|
||||
north,
|
||||
zoom,
|
||||
transport_type,
|
||||
node_type,
|
||||
product_uuid,
|
||||
hub_uuid,
|
||||
supplier_uuid,
|
||||
)
|
||||
return [ClusterPointType(**c) for c in clusters]
|
||||
|
||||
def resolve_products(self, info):
|
||||
|
||||
Reference in New Issue
Block a user