@@ -293,11 +293,16 @@ private void Insert(VectorIndexMetadata metadata, PageAddress dataBlock, float[]
293293 candidates . Where ( x => x . Address != newAddress ) . ToList ( ) ,
294294 VectorIndexNode . MaxNeighborsPerLevel ) ;
295295
296- node . SetNeighbors ( level , selected . Select ( x => x . Address ) . ToList ( ) ) ;
296+ var selectedAddresses = selected . Select ( x => x . Address ) . ToList ( ) ;
297297
298- foreach ( var neighbor in selected )
298+ node . SetNeighbors ( level , selectedAddresses ) ;
299+
300+ foreach ( var neighbor in selectedAddresses )
299301 {
300- this . EnsureBidirectional ( metadata , neighbor . Address , newAddress , level , vectorCache ) ;
302+ if ( ! this . EnsureBidirectional ( metadata , neighbor , newAddress , level , vectorCache ) )
303+ {
304+ node . RemoveNeighbor ( level , neighbor ) ;
305+ }
301306 }
302307
303308 if ( selected . Count > 0 )
@@ -420,10 +425,11 @@ private List<NodeDistance> SearchLayer(
420425 return this . SelectNeighbors ( results , Math . Max ( 1 , maxResults ) ) ;
421426 }
422427
423- private void EnsureBidirectional ( VectorIndexMetadata metadata , PageAddress source , PageAddress target , int level , Dictionary < PageAddress , float [ ] > vectorCache )
428+ private bool EnsureBidirectional ( VectorIndexMetadata metadata , PageAddress source , PageAddress target , int level , Dictionary < PageAddress , float [ ] > vectorCache )
424429 {
425430 var node = this . GetNode ( source ) ;
426- var neighbors = node . GetNeighbors ( level ) . ToList ( ) ;
431+ var neighbors = node . GetNeighbors ( level ) . Where ( x => ! x . IsEmpty ) . ToList ( ) ;
432+ var before = neighbors . ToList ( ) ;
427433
428434 if ( ! neighbors . Contains ( target ) )
429435 {
@@ -432,6 +438,33 @@ private void EnsureBidirectional(VectorIndexMetadata metadata, PageAddress sourc
432438
433439 var pruned = this . PruneNeighbors ( metadata , source , neighbors , vectorCache ) ;
434440 node . SetNeighbors ( level , pruned ) ;
441+
442+ foreach ( var removed in before )
443+ {
444+ if ( ! pruned . Contains ( removed ) )
445+ {
446+ this . RemoveBackLink ( removed , source , level ) ;
447+ }
448+ }
449+
450+ return pruned . Contains ( target ) ;
451+ }
452+
453+ private void RemoveBackLink ( PageAddress source , PageAddress target , int level )
454+ {
455+ if ( source . IsEmpty || target . IsEmpty )
456+ {
457+ return ;
458+ }
459+
460+ var node = this . GetNode ( source ) ;
461+
462+ if ( level < 0 || level >= node . LevelCount )
463+ {
464+ return ;
465+ }
466+
467+ node . RemoveNeighbor ( level , target ) ;
435468 }
436469
437470 private IReadOnlyList < PageAddress > PruneNeighbors ( VectorIndexMetadata metadata , PageAddress source , List < PageAddress > neighbors , Dictionary < PageAddress , float [ ] > vectorCache )
0 commit comments