基于AWS Neptune的无中转航线Gremlin查询构建求助
航空路线图数据库查询扩展与结构优化
现有数据结构
机场顶点CSV数据
~id,code:String PPG,PPG CMH,CMH LGB,LGB HRL,HRL TUS,TUS MEM,MEM YWG,YWG ICN,ICN ATL,ATL MIA,MIA IND,IND TPA,TPA DEN,DEN FLL,FLL DAL,DAL MDW,MDW PHX,PHX HOU,HOU MCO,MCO SJU,SJU
航班边CSV数据
~id,origin:String,destination:String,start_datetime:Date,end_datetime:Date,equipment_type:String,tail_number:String,flight_number:String,~from,~to,~label 1912MIA20230612,MIA,ATL,2023-06-12T09:10:00Z,2023-06-12T11:00:00Z,AB1,111111,1912,MIA,ATL,FLIGHT 0468IND20230612,IND,PHX,2023-06-12T09:20:00Z,2023-06-12T13:00:00Z,AB2,222222,468,IND,PHX,FLIGHT 2826TPA20230612,TPA,DEN,2023-06-12T09:20:00Z,2023-06-12T16:42:00Z,AB3,333333,2826,TPA,DEN,FLIGHT 3629FLL20230612,FLL,ATL,2023-06-12T09:35:00Z,2023-06-12T11:25:00Z,AB4,444444,3629,FLL,ATL,FLIGHT 2970FLL20230612,FLL,DAL,2023-06-12T09:45:00Z,2023-06-12T16:55:00Z,AB1,555555,2970,FLL,DAL,FLIGHT 1855MDW20230612,MDW,PHX,2023-06-12T10:00:00Z,2023-06-12T15:27:00Z,AB1,666666,1855,MDW,PHX,FLIGHT 2910HOU20230612,HOU,ATL,2023-06-12T10:00:00Z,2023-06-12T12:00:00Z,AB5,777777,2910,HOU,ATL,FLIGHT 0169ATL20230612,ATL,DEN,2023-06-12T10:05:00Z,2023-06-12T16:30:00Z,AB3,888888,169,ATL,DEN,FLIGHT 1736MCO20230612,MCO,SJU,2023-06-12T10:05:00Z,2023-06-12T16:52:00Z,AB1,999999,1736,MCO,SJU,FLIGHT
现有直达航班查询
已实现特定时间段内起讫地直达航班的Gremlin查询:
g.V(). has('code', 'MDW').as('a'). outE('FLIGHT').as('e'). filter( select('e'). values('start_datetime'). is(gte(datetime('2023-06-12T10:00:00Z')))). inV(). has('code', 'ATL'). filter( select('e'). values('end_datetime'). is(lte(datetime('2023-07-19T00:00:00Z')))). select('a', 'e').by(valueMap('code')).by(valueMap())
一、扩展查询:同一尾号飞机执飞的经停航线(最多4个经停点)
针对同一tail_number飞机执飞、最多4个经停点的航线查询,需满足:同一飞机执飞、航班时间衔接合理、整体在指定时间段内。以下是实现语句:
扩展后的Gremlin查询
// 定义查询参数 def start_time = datetime('2023-06-12T10:00:00Z') def end_time = datetime('2023-07-19T00:00:00Z') def origin_code = 'MDW' def dest_code = 'ATL' def max_stops = 4 // 最多4个经停点,对应最多5段航班 g.V().has('code', origin_code).as('origin'). // 匹配第一段航班,记录初始信息 outE('FLIGHT').as('e1'). filter(values('start_datetime').is(gte(start_time))). inV().as('v1'). // 重复遍历后续航班,最多4次(对应4个经停点) repeat( outE('FLIGHT').as('e'). // 验证同一飞机执飞,且下一段起飞晚于上一段到达 filter( select(prev('e')).values('tail_number').is(eq(values('tail_number'))).and( select(prev('e')).values('end_datetime').is(lte(values('start_datetime'))) ) ). inV().as('v') ).times(max_stops). // 到达目标机场 has('code', dest_code).as('dest'). // 过滤最终航班的到达时间不超过截止时间 filter(select(last('e')).values('end_datetime').is(lte(end_time))). // 收集完整路径信息 select('origin', 'v1', 'v', 'dest', 'e1', 'e'). by(valueMap('code')). by(valueMap('code')). by(valueMap('code')). by(valueMap('code')). by(valueMap()). by(valueMap())
查询说明
- 用
repeat().times(max_stops)控制遍历次数,确保最多4个经停点 - 每次遍历验证
tail_number一致性和航班时间衔接逻辑 - 最终过滤整个航线的结束时间,确保符合时间段要求
- 通过
select收集完整的节点和航段信息,便于查看完整航线
二、顶点与边结构优化建议
1. 采用「机场+日期」复合顶点
你考虑的这个方向能有效提升查询性能,核心优势:
- 减少过滤开销:将每日机场作为独立顶点,航班边直接关联当日顶点,无需反复过滤日期维度
- 精准定位查询:按日期查询时可直接定位到对应顶点,避免全量扫描
- 数据隔离:不同日期的航班数据物理隔离,便于归档或清理
实现方式
- 顶点
~id格式改为机场代码_日期(如MDW_20230612) - 顶点属性保留
code(机场代码)、date(日期) - 航班边的
~from/~to对应复合顶点的~id,可保留origin/destination用于跨日期关联
2. 索引优化
为加速查询,建议创建以下索引:
- 顶点索引:给机场顶点的
code创建唯一索引;若用复合顶点,给code+date创建复合索引 - 边索引:给
FLIGHT边的tail_number创建索引,给start_datetime/end_datetime创建范围索引;若用复合顶点,给~from/~to创建索引 - 复合索引:针对
tail_number+start_datetime这类常见查询组合创建复合索引
3. 可选:引入飞机顶点
若需关联飞机的额外属性(如机型、所属航司),可将tail_number抽象为独立顶点:
- 飞机顶点
~id为tail_number值,属性包含equipment_type、airline等 - 航班边新增关联指向飞机顶点,形成「机场 ←FLIGHT→ 机场 ←OPERATED_BY→ 飞机」的结构
- 优势:避免边中重复存储飞机属性,便于查询同一飞机的所有历史航班
4. 边属性简化
现有边中origin/destination与~from/~to内容重复,若无需跨日期关联可移除,减少存储开销;若需保留用于跨日期衔接场景则保留。
内容的提问来源于stack exchange,提问作者terrabl
相关产品推荐
相关产品推荐

