feat(schema): add bounds filtering to list endpoints
All checks were successful
Build Docker Image / build (push) Successful in 1m16s
All checks were successful
Build Docker Image / build (push) Successful in 1m16s
Add west, south, east, north params to: - hubs_list - suppliers_list - products_list This enables filtering by map viewport bounds for the catalog.
This commit is contained in:
@@ -365,6 +365,10 @@ class Query(graphene.ObjectType):
|
|||||||
offset=graphene.Int(default_value=0, description="Offset for pagination"),
|
offset=graphene.Int(default_value=0, description="Offset for pagination"),
|
||||||
country=graphene.String(description="Filter by country name"),
|
country=graphene.String(description="Filter by country name"),
|
||||||
transport_type=graphene.String(description="Filter by transport type"),
|
transport_type=graphene.String(description="Filter by transport type"),
|
||||||
|
west=graphene.Float(description="Bounding box west longitude"),
|
||||||
|
south=graphene.Float(description="Bounding box south latitude"),
|
||||||
|
east=graphene.Float(description="Bounding box east longitude"),
|
||||||
|
north=graphene.Float(description="Bounding box north latitude"),
|
||||||
description="Get paginated list of logistics hubs",
|
description="Get paginated list of logistics hubs",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -373,6 +377,10 @@ class Query(graphene.ObjectType):
|
|||||||
limit=graphene.Int(default_value=50, description="Max results"),
|
limit=graphene.Int(default_value=50, description="Max results"),
|
||||||
offset=graphene.Int(default_value=0, description="Offset for pagination"),
|
offset=graphene.Int(default_value=0, description="Offset for pagination"),
|
||||||
country=graphene.String(description="Filter by country name"),
|
country=graphene.String(description="Filter by country name"),
|
||||||
|
west=graphene.Float(description="Bounding box west longitude"),
|
||||||
|
south=graphene.Float(description="Bounding box south latitude"),
|
||||||
|
east=graphene.Float(description="Bounding box east longitude"),
|
||||||
|
north=graphene.Float(description="Bounding box north latitude"),
|
||||||
description="Get paginated list of suppliers from graph",
|
description="Get paginated list of suppliers from graph",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -380,6 +388,10 @@ class Query(graphene.ObjectType):
|
|||||||
ProductType,
|
ProductType,
|
||||||
limit=graphene.Int(default_value=50, description="Max results"),
|
limit=graphene.Int(default_value=50, description="Max results"),
|
||||||
offset=graphene.Int(default_value=0, description="Offset for pagination"),
|
offset=graphene.Int(default_value=0, description="Offset for pagination"),
|
||||||
|
west=graphene.Float(description="Bounding box west longitude"),
|
||||||
|
south=graphene.Float(description="Bounding box south latitude"),
|
||||||
|
east=graphene.Float(description="Bounding box east longitude"),
|
||||||
|
north=graphene.Float(description="Bounding box north latitude"),
|
||||||
description="Get paginated list of products from graph",
|
description="Get paginated list of products from graph",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1683,30 +1695,52 @@ class Query(graphene.ObjectType):
|
|||||||
logger.error("Error finding route to coordinates: %s", e)
|
logger.error("Error finding route to coordinates: %s", e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def resolve_hubs_list(self, info, limit=50, offset=0, country=None, transport_type=None):
|
def resolve_hubs_list(self, info, limit=50, offset=0, country=None, transport_type=None,
|
||||||
|
west=None, south=None, east=None, north=None):
|
||||||
"""Get paginated list of logistics hubs."""
|
"""Get paginated list of logistics hubs."""
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
||||||
aql = """
|
# Build bounds filter if all bounds are provided
|
||||||
|
bounds_filter = ""
|
||||||
|
if west is not None and south is not None and east is not None and north is not None:
|
||||||
|
bounds_filter = """
|
||||||
|
FILTER node.latitude != null AND node.longitude != null
|
||||||
|
FILTER node.latitude >= @south AND node.latitude <= @north
|
||||||
|
FILTER node.longitude >= @west AND node.longitude <= @east
|
||||||
|
"""
|
||||||
|
|
||||||
|
aql = f"""
|
||||||
FOR node IN nodes
|
FOR node IN nodes
|
||||||
FILTER node.node_type == 'logistics' OR node.node_type == null
|
FILTER node.node_type == 'logistics' OR node.node_type == null
|
||||||
FILTER node.product_uuid == null
|
FILTER node.product_uuid == null
|
||||||
LET types = node.transport_types != null ? node.transport_types : []
|
LET types = node.transport_types != null ? node.transport_types : []
|
||||||
FILTER @transport_type == null OR @transport_type IN types
|
FILTER @transport_type == null OR @transport_type IN types
|
||||||
FILTER @country == null OR node.country == @country
|
FILTER @country == null OR node.country == @country
|
||||||
|
{bounds_filter}
|
||||||
SORT node.name ASC
|
SORT node.name ASC
|
||||||
LIMIT @offset, @limit
|
LIMIT @offset, @limit
|
||||||
RETURN node
|
RETURN node
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
bind_vars = {
|
||||||
cursor = db.aql.execute(aql, bind_vars={
|
'transport_type': transport_type,
|
||||||
'transport_type': transport_type,
|
'country': country,
|
||||||
'country': country,
|
'offset': offset,
|
||||||
'offset': offset,
|
'limit': limit,
|
||||||
'limit': limit,
|
}
|
||||||
|
|
||||||
|
# Only add bounds to bind_vars if they are used
|
||||||
|
if west is not None and south is not None and east is not None and north is not None:
|
||||||
|
bind_vars.update({
|
||||||
|
'west': west,
|
||||||
|
'south': south,
|
||||||
|
'east': east,
|
||||||
|
'north': north,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor = db.aql.execute(aql, bind_vars=bind_vars)
|
||||||
|
|
||||||
hubs = []
|
hubs = []
|
||||||
for node in cursor:
|
for node in cursor:
|
||||||
hubs.append(NodeType(
|
hubs.append(NodeType(
|
||||||
@@ -1726,26 +1760,48 @@ class Query(graphene.ObjectType):
|
|||||||
logger.error("Error getting hubs list: %s", e)
|
logger.error("Error getting hubs list: %s", e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def resolve_suppliers_list(self, info, limit=50, offset=0, country=None):
|
def resolve_suppliers_list(self, info, limit=50, offset=0, country=None,
|
||||||
|
west=None, south=None, east=None, north=None):
|
||||||
"""Get paginated list of suppliers from graph."""
|
"""Get paginated list of suppliers from graph."""
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
||||||
aql = """
|
# Build bounds filter if all bounds are provided
|
||||||
|
bounds_filter = ""
|
||||||
|
if west is not None and south is not None and east is not None and north is not None:
|
||||||
|
bounds_filter = """
|
||||||
|
FILTER node.latitude != null AND node.longitude != null
|
||||||
|
FILTER node.latitude >= @south AND node.latitude <= @north
|
||||||
|
FILTER node.longitude >= @west AND node.longitude <= @east
|
||||||
|
"""
|
||||||
|
|
||||||
|
aql = f"""
|
||||||
FOR node IN nodes
|
FOR node IN nodes
|
||||||
FILTER node.node_type == 'supplier'
|
FILTER node.node_type == 'supplier'
|
||||||
FILTER @country == null OR node.country == @country
|
FILTER @country == null OR node.country == @country
|
||||||
|
{bounds_filter}
|
||||||
SORT node.name ASC
|
SORT node.name ASC
|
||||||
LIMIT @offset, @limit
|
LIMIT @offset, @limit
|
||||||
RETURN node
|
RETURN node
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
bind_vars = {
|
||||||
cursor = db.aql.execute(aql, bind_vars={
|
'country': country,
|
||||||
'country': country,
|
'offset': offset,
|
||||||
'offset': offset,
|
'limit': limit,
|
||||||
'limit': limit,
|
}
|
||||||
|
|
||||||
|
# Only add bounds to bind_vars if they are used
|
||||||
|
if west is not None and south is not None and east is not None and north is not None:
|
||||||
|
bind_vars.update({
|
||||||
|
'west': west,
|
||||||
|
'south': south,
|
||||||
|
'east': east,
|
||||||
|
'north': north,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor = db.aql.execute(aql, bind_vars=bind_vars)
|
||||||
|
|
||||||
suppliers = []
|
suppliers = []
|
||||||
for node in cursor:
|
for node in cursor:
|
||||||
suppliers.append(SupplierType(
|
suppliers.append(SupplierType(
|
||||||
@@ -1760,30 +1816,52 @@ class Query(graphene.ObjectType):
|
|||||||
logger.error("Error getting suppliers list: %s", e)
|
logger.error("Error getting suppliers list: %s", e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def resolve_products_list(self, info, limit=50, offset=0):
|
def resolve_products_list(self, info, limit=50, offset=0,
|
||||||
|
west=None, south=None, east=None, north=None):
|
||||||
"""Get paginated list of products from graph."""
|
"""Get paginated list of products from graph."""
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
||||||
aql = """
|
# Build bounds filter if all bounds are provided
|
||||||
|
bounds_filter = ""
|
||||||
|
if west is not None and south is not None and east is not None and north is not None:
|
||||||
|
bounds_filter = """
|
||||||
|
FILTER node.latitude != null AND node.longitude != null
|
||||||
|
FILTER node.latitude >= @south AND node.latitude <= @north
|
||||||
|
FILTER node.longitude >= @west AND node.longitude <= @east
|
||||||
|
"""
|
||||||
|
|
||||||
|
aql = f"""
|
||||||
FOR node IN nodes
|
FOR node IN nodes
|
||||||
FILTER node.node_type == 'offer'
|
FILTER node.node_type == 'offer'
|
||||||
FILTER node.product_uuid != null
|
FILTER node.product_uuid != null
|
||||||
|
{bounds_filter}
|
||||||
COLLECT product_uuid = node.product_uuid INTO offers
|
COLLECT product_uuid = node.product_uuid INTO offers
|
||||||
LET first_offer = FIRST(offers).node
|
LET first_offer = FIRST(offers).node
|
||||||
SORT first_offer.product_name ASC
|
SORT first_offer.product_name ASC
|
||||||
LIMIT @offset, @limit
|
LIMIT @offset, @limit
|
||||||
RETURN {
|
RETURN {{
|
||||||
uuid: product_uuid,
|
uuid: product_uuid,
|
||||||
name: first_offer.product_name
|
name: first_offer.product_name
|
||||||
}
|
}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
bind_vars = {
|
||||||
cursor = db.aql.execute(aql, bind_vars={
|
'offset': offset,
|
||||||
'offset': offset,
|
'limit': limit,
|
||||||
'limit': limit,
|
}
|
||||||
|
|
||||||
|
# Only add bounds to bind_vars if they are used
|
||||||
|
if west is not None and south is not None and east is not None and north is not None:
|
||||||
|
bind_vars.update({
|
||||||
|
'west': west,
|
||||||
|
'south': south,
|
||||||
|
'east': east,
|
||||||
|
'north': north,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor = db.aql.execute(aql, bind_vars=bind_vars)
|
||||||
|
|
||||||
products = [ProductType(uuid=p['uuid'], name=p.get('name')) for p in cursor]
|
products = [ProductType(uuid=p['uuid'], name=p.get('name')) for p in cursor]
|
||||||
logger.info("Returning %d products (offset=%d, limit=%d)", len(products), offset, limit)
|
logger.info("Returning %d products (offset=%d, limit=%d)", len(products), offset, limit)
|
||||||
return products
|
return products
|
||||||
|
|||||||
Reference in New Issue
Block a user