package graph import "fmt" // QueryTemplates contains reusable Cypher query templates type QueryTemplates struct{} // NewQueryTemplates creates a new query templates instance func NewQueryTemplates() *QueryTemplates { return &QueryTemplates{} } // FindResourceChainsQuery returns the Cypher query for finding resource chains func (qt *QueryTemplates) FindResourceChainsQuery(maxLength int) string { return fmt.Sprintf(` MATCH (start:ResourceFlow {type: $resource_type, direction: "output"}) MATCH path = (start)-[:MATCHES*1..%d]-(connected:ResourceFlow) WHERE connected.direction = "input" AND connected.type = $resource_type AND start <> connected WITH path, nodes(path) AS pathNodes, relationships(path) AS pathRels WHERE size(pathNodes) >= 2 AND size(pathNodes) <= %d // Get sites for distance calculation MATCH (startSite:Site)-[:HOSTS]->(start) MATCH (endSite:Site)-[:HOSTS]->(connected) WHERE startSite.latitude IS NOT NULL AND startSite.longitude IS NOT NULL AND endSite.latitude IS NOT NULL AND endSite.longitude IS NOT NULL // Calculate total distance along the path WITH path, pathNodes, pathRels, startSite, endSite, point.distance( point({latitude: startSite.latitude, longitude: startSite.longitude}), point({latitude: endSite.latitude, longitude: endSite.longitude}) ) / 1000.0 AS total_distance WHERE total_distance <= $max_distance // Get organization information OPTIONAL MATCH (startOrg:Organization)-[:OPERATES_AT]->(startSite) OPTIONAL MATCH (endOrg:Organization)-[:OPERATES_AT]->(endSite) // Calculate total value from relationships WITH path, pathNodes, pathRels, total_distance, startOrg, endOrg, reduce(totalValue = 0.0, rel IN pathRels | totalValue + COALESCE(rel.economic_value, 0.0) ) AS total_value WHERE total_value >= $min_value RETURN pathNodes, pathRels, total_distance, total_value, startOrg.id AS start_org_id, startOrg.name AS start_org_name, endOrg.id AS end_org_id, endOrg.name AS end_org_name ORDER BY total_value DESC, total_distance ASC LIMIT $limit `, maxLength, maxLength) } // FindSymbiosisNetworksQuery returns the Cypher query for finding symbiosis networks func (qt *QueryTemplates) FindSymbiosisNetworksQuery() string { return ` MATCH (o1:Organization)-[:PRODUCES|CONSUMES]->(rf1:ResourceFlow) MATCH (rf1)-[m:MATCHES]-(rf2:ResourceFlow) MATCH (rf2)<-[:PRODUCES|CONSUMES]-(o2:Organization) WHERE o1 <> o2 WITH o1, o2, m, rf1, rf2 // Get site information for distance calculation MATCH (s1:Site)-[:HOSTS]->(rf1) MATCH (s2:Site)-[:HOSTS]->(rf2) WHERE s1.latitude IS NOT NULL AND s2.latitude IS NOT NULL WITH o1, o2, m, rf1, rf2, s1, s2, point.distance( point({latitude: s1.latitude, longitude: s1.longitude}), point({latitude: s2.latitude, longitude: s2.longitude}) ) / 1000.0 AS distance_km // Group by connected organizations WITH o1.id AS org1_id, o1.name AS org1_name, o1.latitude AS org1_lat, o1.longitude AS org1_lng, o2.id AS org2_id, o2.name AS org2_name, o2.latitude AS org2_lat, o2.longitude AS org2_lng, collect(DISTINCT { flow_id: rf1.id, resource_type: rf1.type, match_id: m.match_id, economic_value: m.economic_value, distance: distance_km }) AS connections WHERE size(connections) >= 2 // Aggregate network metrics WITH collect(DISTINCT org1_id) + collect(DISTINCT org2_id) AS network_orgs, connections, reduce(totalValue = 0.0, conn IN connections | totalValue + COALESCE(conn.economic_value, 0.0) ) AS total_value, reduce(maxDist = 0.0, conn IN connections | CASE WHEN conn.distance > maxDist THEN conn.distance ELSE maxDist END ) AS max_distance WHERE size(network_orgs) >= $min_orgs AND size(network_orgs) <= $max_size RETURN network_orgs, connections, total_value, max_distance ORDER BY total_value DESC LIMIT $limit ` } // FindOptimalPathQuery returns the Cypher query for finding optimal paths func (qt *QueryTemplates) FindOptimalPathQuery(maxHops int) string { return fmt.Sprintf(` MATCH (source:Organization {id: $source_org}) MATCH (target:Organization {id: $target_org}) // Find paths through resource flows MATCH path = shortestPath( (source)-[:PRODUCES|CONSUMES|OPERATES_AT*1..%d]-(target) ) WITH path, nodes(path) AS pathNodes, relationships(path) AS pathRels WHERE size(pathNodes) >= 2 // Extract resource flows from path WITH path, pathNodes, pathRels, [node IN pathNodes WHERE node:ResourceFlow] AS flowNodes, [rel IN pathRels WHERE type(rel) = 'MATCHES'] AS matchRels WHERE size(flowNodes) >= 1 AND size(matchRels) >= 1 // Calculate path cost WITH path, pathNodes, pathRels, flowNodes, matchRels, reduce(totalCost = 0.0, rel IN matchRels | totalCost + COALESCE(rel.transport_cost, 0.0) + COALESCE(rel.processing_cost, 0.0) ) AS total_cost, reduce(totalDist = 0.0, rel IN matchRels | totalDist + COALESCE(rel.distance_km, 0.0) ) AS total_distance WHERE total_distance <= $max_distance RETURN pathNodes, pathRels, total_cost, total_distance, length(path) AS path_length ORDER BY total_cost ASC, total_distance ASC LIMIT $limit `, maxHops*2) } // CalculateCentralityQuery returns the Cypher query for calculating centrality func (qt *QueryTemplates) CalculateCentralityQuery() string { return ` MATCH (o:Organization) OPTIONAL MATCH (o)-[:PRODUCES|CONSUMES]->(rf1:ResourceFlow)-[:MATCHES]-(rf2:ResourceFlow)<-[:PRODUCES|CONSUMES]-(other:Organization) WHERE o <> other WITH o.id AS org_id, count(DISTINCT other) AS degree_centrality, count(DISTINCT rf1) AS out_flows, count(DISTINCT rf2) AS in_flows WHERE degree_centrality > 0 RETURN org_id, degree_centrality, out_flows, in_flows ORDER BY degree_centrality DESC ` } // GetNetworkStatisticsQuery returns the Cypher query for network statistics func (qt *QueryTemplates) GetNetworkStatisticsQuery() string { return ` MATCH (o:Organization) OPTIONAL MATCH (o)-[:PRODUCES|CONSUMES]->(rf:ResourceFlow) OPTIONAL MATCH (rf)-[m:MATCHES]-(rf2:ResourceFlow) OPTIONAL MATCH (rf2)<-[:PRODUCES|CONSUMES]-(o2:Organization) WHERE o <> o2 WITH count(DISTINCT o) AS total_organizations, count(DISTINCT rf) AS total_resource_flows, count(DISTINCT m) AS total_matches, sum(DISTINCT m.economic_value) AS total_economic_value, avg(m.distance_km) AS avg_distance, count(DISTINCT CASE WHEN m.economic_value > 50000 THEN m END) AS high_value_matches MATCH (o:Organization)-[:OPERATES_AT]->(s:Site) WITH total_organizations, total_resource_flows, total_matches, total_economic_value, avg_distance, high_value_matches, collect(DISTINCT {lat: s.latitude, lng: s.longitude}) AS locations // Calculate geographic span WITH total_organizations, total_resource_flows, total_matches, total_economic_value, avg_distance, high_value_matches, locations, reduce(maxLat = -90, loc IN locations | CASE WHEN loc.lat > maxLat THEN loc.lat ELSE maxLat END) AS max_lat, reduce(minLat = 90, loc IN locations | CASE WHEN loc.lat < minLat THEN loc.lat ELSE minLat END) AS min_lat, reduce(maxLng = -180, loc IN locations | CASE WHEN loc.lng > maxLng THEN loc.lng ELSE maxLng END) AS max_lng, reduce(minLng = 180, loc IN locations | CASE WHEN loc.lng < minLng THEN loc.lng ELSE minLng END) AS min_lng RETURN total_organizations, total_resource_flows, total_matches, total_economic_value, avg_distance, high_value_matches, point.distance( point({latitude: min_lat, longitude: min_lng}), point({latitude: max_lat, longitude: max_lng}) ) / 1000.0 AS geographic_span_km ` } // FindCircularEconomyCyclesQuery returns the Cypher query for finding circular economy cycles func (qt *QueryTemplates) FindCircularEconomyCyclesQuery() string { return ` // Find circular resource flows (waste -> recycling -> reuse -> waste) MATCH cycle = (start:ResourceFlow)-[r:MATCHES*3..6]-(start) WHERE start.direction = "output" AND ALL(i IN range(0, length(r)-2) WHERE nodes(cycle)[i].direction <> nodes(cycle)[i+1].direction) WITH cycle, length(r) AS cycle_length, [node IN nodes(cycle) | node.type] AS resource_types, [node IN nodes(cycle) | node.id] AS flow_ids, reduce(totalValue = 0.0, rel IN r | totalValue + rel.economic_value) AS cycle_value WHERE cycle_value > 0 // Get organization information for each cycle MATCH (org:Organization)-[:PRODUCES|CONSUMES]->(flow:ResourceFlow) WHERE flow IN nodes(cycle) WITH cycle, cycle_length, resource_types, flow_ids, cycle_value, collect(DISTINCT org.name) AS organizations, count(DISTINCT org) AS org_count WHERE org_count >= 3 RETURN cycle, cycle_length, resource_types, flow_ids, cycle_value, organizations, org_count ORDER BY cycle_value DESC LIMIT $limit ` }