@@ -58,18 +58,38 @@ pub async fn execute_path(
5858 let coordinator = runtime. search_coordinator ( ) ;
5959 let server_id = runtime. server_id ( ) ;
6060 let ( starts, goals, reverse_path) = select_shortest_path_search_plan ( & from_ids, & to_ids) ;
61+ let best = if query. all_candidates {
62+ let mut best: Option < ( usize , Vec < Id > ) > = None ;
63+ for & goal in goals {
64+ let mut result = run_bfs (
65+ & coordinator,
66+ server_id,
67+ starts,
68+ & [ goal] ,
69+ & query,
70+ runtime,
71+ reverse_path,
72+ )
73+ . await ?;
6174
62- // BfsSearchConfig accepts a single goal. Run repeated BFS searches against
63- // the smaller endpoint set and reverse the resulting path when we search
64- // from the destination side.
65- let mut best: Option < ( usize , Vec < Id > ) > = None ;
66-
67- for & goal in goals {
75+ if result. found {
76+ if reverse_path {
77+ result. path . reverse ( ) ;
78+ }
79+ let hops = result. path . len ( ) . saturating_sub ( 1 ) ;
80+ let is_better = best. as_ref ( ) . map_or ( true , |( prev, _) | hops < * prev) ;
81+ if is_better {
82+ best = Some ( ( hops, result. path ) ) ;
83+ }
84+ }
85+ }
86+ best
87+ } else {
6888 let mut result = run_bfs (
6989 & coordinator,
7090 server_id,
7191 starts,
72- goal ,
92+ goals ,
7393 & query,
7494 runtime,
7595 reverse_path,
@@ -80,13 +100,11 @@ pub async fn execute_path(
80100 if reverse_path {
81101 result. path . reverse ( ) ;
82102 }
83- let hops = result. path . len ( ) . saturating_sub ( 1 ) ;
84- let is_better = best. as_ref ( ) . map_or ( true , |( prev, _) | hops < * prev) ;
85- if is_better {
86- best = Some ( ( hops, result. path ) ) ;
87- }
103+ Some ( ( result. path . len ( ) . saturating_sub ( 1 ) , result. path ) )
104+ } else {
105+ None
88106 }
89- }
107+ } ;
90108
91109 let Some ( ( hops, path_ids) ) = best else {
92110 return Ok ( ShortestPathResult {
@@ -165,7 +183,17 @@ pub async fn execute_paths(
165183 . await ;
166184 }
167185
168- let goal_set: HashSet < Id > = to_ids. iter ( ) . copied ( ) . collect ( ) ;
186+ let goal_set: HashSet < Id > = if query. all_candidates {
187+ to_ids. iter ( ) . copied ( ) . collect ( )
188+ } else if let Some ( goal_id) = shortest_path_ids
189+ . as_ref ( )
190+ . and_then ( |path| path. last ( ) )
191+ . copied ( )
192+ {
193+ HashSet :: from ( [ goal_id] )
194+ } else {
195+ to_ids. iter ( ) . copied ( ) . collect ( )
196+ } ;
169197 let direction_variants = distributed_directions_for_edge_schemas (
170198 runtime,
171199 & query. edge_schema_ids ,
@@ -268,14 +296,38 @@ async fn find_best_shortest_path_ids_for_paths(
268296 let coordinator = runtime. search_coordinator ( ) ;
269297 let server_id = runtime. server_id ( ) ;
270298 let ( starts, goals, reverse_path) = select_shortest_path_search_plan ( from_ids, to_ids) ;
271- let mut best: Option < ( usize , Vec < Id > ) > = None ;
299+ let best = if query. all_candidates {
300+ let mut best: Option < ( usize , Vec < Id > ) > = None ;
301+ for & goal in goals {
302+ let mut result = run_bfs_for_paths (
303+ & coordinator,
304+ server_id,
305+ starts,
306+ & [ goal] ,
307+ query,
308+ runtime,
309+ reverse_path,
310+ )
311+ . await ?;
272312
273- for & goal in goals {
313+ if result. found {
314+ if reverse_path {
315+ result. path . reverse ( ) ;
316+ }
317+ let hops = result. path . len ( ) . saturating_sub ( 1 ) ;
318+ let is_better = best. as_ref ( ) . map_or ( true , |( prev, _) | hops < * prev) ;
319+ if is_better {
320+ best = Some ( ( hops, result. path ) ) ;
321+ }
322+ }
323+ }
324+ best
325+ } else {
274326 let mut result = run_bfs_for_paths (
275327 & coordinator,
276328 server_id,
277329 starts,
278- goal ,
330+ goals ,
279331 query,
280332 runtime,
281333 reverse_path,
@@ -286,13 +338,11 @@ async fn find_best_shortest_path_ids_for_paths(
286338 if reverse_path {
287339 result. path . reverse ( ) ;
288340 }
289- let hops = result. path . len ( ) . saturating_sub ( 1 ) ;
290- let is_better = best. as_ref ( ) . map_or ( true , |( prev, _) | hops < * prev) ;
291- if is_better {
292- best = Some ( ( hops, result. path ) ) ;
293- }
341+ Some ( ( result. path . len ( ) . saturating_sub ( 1 ) , result. path ) )
342+ } else {
343+ None
294344 }
295- }
345+ } ;
296346
297347 Ok ( best. map ( |( _, path) | path) )
298348}
@@ -301,7 +351,7 @@ async fn run_bfs_for_paths(
301351 coordinator : & SearchCoordinator ,
302352 server_id : u64 ,
303353 start : & [ Id ] ,
304- goal : Id ,
354+ goals : & [ Id ] ,
305355 query : & BoundPathsQuery ,
306356 runtime : & Arc < MorpheusRuntime > ,
307357 reverse_direction : bool ,
@@ -326,7 +376,7 @@ async fn run_bfs_for_paths(
326376 server_id,
327377 BfsSearchConfig {
328378 start : start. to_vec ( ) ,
329- goal ,
379+ goals : goals . to_vec ( ) ,
330380 max_depth : query. max_depth as u32 ,
331381 max_visited : query. max_visited ,
332382 expand_options : ExpandJobOptions {
@@ -408,7 +458,7 @@ async fn run_bfs(
408458 coordinator : & SearchCoordinator ,
409459 server_id : u64 ,
410460 start : & [ Id ] ,
411- goal : Id ,
461+ goals : & [ Id ] ,
412462 query : & BoundShortestPathQuery ,
413463 runtime : & Arc < MorpheusRuntime > ,
414464 reverse_direction : bool ,
@@ -433,7 +483,7 @@ async fn run_bfs(
433483 server_id,
434484 BfsSearchConfig {
435485 start : start. to_vec ( ) ,
436- goal ,
486+ goals : goals . to_vec ( ) ,
437487 max_depth : query. max_depth as u32 ,
438488 max_visited : query. max_visited ,
439489 expand_options : ExpandJobOptions {
0 commit comments