@@ -609,8 +609,7 @@ fn delete_one_item() {
609
609
Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 4, 5]>, roots: [0], distance: "euclidean" }
610
610
Tree 0: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Item(0), right: Tree(4), normal: [1.0000, 0.0000] })
611
611
Tree 1: Descendants(Descendants { descendants: [1, 5] })
612
- Tree 2: Descendants(Descendants { descendants: [4] })
613
- Tree 3: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(2), right: Item(2), normal: [0.0000, 0.0000] })
612
+ Tree 3: Descendants(Descendants { descendants: [2, 4] })
614
613
Tree 4: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(1), right: Tree(3), normal: [0.0000, 0.0000] })
615
614
Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [0.0000, 0.0000] })
616
615
Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [1.0000, 0.0000] })
@@ -634,8 +633,7 @@ fn delete_one_item() {
634
633
Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 2, 4, 5]>, roots: [0], distance: "euclidean" }
635
634
Tree 0: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Item(0), right: Tree(4), normal: [1.0000, 0.0000] })
636
635
Tree 1: Descendants(Descendants { descendants: [5] })
637
- Tree 2: Descendants(Descendants { descendants: [4] })
638
- Tree 3: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(2), right: Item(2), normal: [0.0000, 0.0000] })
636
+ Tree 3: Descendants(Descendants { descendants: [2, 4] })
639
637
Tree 4: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(1), right: Tree(3), normal: [0.0000, 0.0000] })
640
638
Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [0.0000, 0.0000] })
641
639
Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [2.0000, 0.0000] })
@@ -909,8 +907,10 @@ fn delete_extraneous_tree() {
909
907
"### ) ;
910
908
}
911
909
910
+ // If we have multiple split node and empty all the branch of the top split node (root node)
911
+ // See https://github.com/meilisearch/arroy/issues/117
912
912
#[ test]
913
- fn reuse_node_id ( ) {
913
+ fn create_root_split_node_with_empty_child ( ) {
914
914
let handle = create_database :: < Euclidean > ( ) ;
915
915
let mut rng = rng ( ) ;
916
916
let mut wtxn = handle. env . write_txn ( ) . unwrap ( ) ;
@@ -942,32 +942,38 @@ fn reuse_node_id() {
942
942
let mut wtxn = handle. env . write_txn ( ) . unwrap ( ) ;
943
943
let writer = Writer :: new ( handle. database , 0 , 2 ) ;
944
944
945
- // if we delete the 1 it should free the node id 0
945
+ // if we delete the 1 and 5 the tree node 4 should remove itself and be replaced by the 3rd one
946
946
writer. del_item ( & mut wtxn, 1 ) . unwrap ( ) ;
947
+ writer. del_item ( & mut wtxn, 5 ) . unwrap ( ) ;
947
948
writer. builder ( & mut rng) . n_trees ( 1 ) . build ( & mut wtxn) . unwrap ( ) ;
948
949
wtxn. commit ( ) . unwrap ( ) ;
949
950
950
951
insta:: assert_snapshot!( handle, @r###"
951
952
==================
952
953
Dumping index 0
953
- Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 2, 3, 4, 5 ]>, roots: [0], distance: "euclidean" }
954
+ Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 2, 3, 4]>, roots: [0], distance: "euclidean" }
954
955
Tree 0: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Item(0), right: Tree(4), normal: [1.0000, 0.0000] })
955
- Tree 1: Descendants(Descendants { descendants: [5 ] })
956
+ Tree 1: Descendants(Descendants { descendants: [] })
956
957
Tree 2: Descendants(Descendants { descendants: [3, 4] })
957
958
Tree 3: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(2), right: Item(2), normal: [0.0000, 0.0000] })
958
959
Tree 4: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(1), right: Tree(3), normal: [0.0000, 0.0000] })
959
960
Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [0.0000, 0.0000] })
960
961
Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [2.0000, 0.0000] })
961
962
Item 3: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [3.0000, 0.0000] })
962
963
Item 4: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [4.0000, 0.0000] })
963
- Item 5: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [5.0000, 0.0000] })
964
964
"### ) ;
965
+ }
965
966
967
+ #[ test]
968
+ fn reuse_node_id ( ) {
969
+ let handle = create_database :: < Euclidean > ( ) ;
970
+ let mut rng = rng ( ) ;
966
971
let mut wtxn = handle. env . write_txn ( ) . unwrap ( ) ;
967
972
let writer = Writer :: new ( handle. database , 0 , 2 ) ;
968
973
969
- // if we re-insert the 1 the node id 0 should be re-used
970
- writer. add_item ( & mut wtxn, 1 , & [ 1. , 0. ] ) . unwrap ( ) ;
974
+ for i in 0 ..6 {
975
+ writer. add_item ( & mut wtxn, i, & [ i as f32 , 0. ] ) . unwrap ( ) ;
976
+ }
971
977
writer. builder ( & mut rng) . n_trees ( 1 ) . build ( & mut wtxn) . unwrap ( ) ;
972
978
wtxn. commit ( ) . unwrap ( ) ;
973
979
@@ -976,11 +982,59 @@ fn reuse_node_id() {
976
982
Dumping index 0
977
983
Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0], distance: "euclidean" }
978
984
Tree 0: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Item(0), right: Tree(4), normal: [1.0000, 0.0000] })
979
- Tree 1: Descendants(Descendants { descendants: [5] })
980
- Tree 2: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(5), right: Item(1), normal: [0.0000, 0.0000 ] })
985
+ Tree 1: Descendants(Descendants { descendants: [1, 5] })
986
+ Tree 2: Descendants(Descendants { descendants: [3, 4 ] })
981
987
Tree 3: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(2), right: Item(2), normal: [0.0000, 0.0000] })
982
988
Tree 4: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(1), right: Tree(3), normal: [0.0000, 0.0000] })
983
- Tree 5: Descendants(Descendants { descendants: [3, 4] })
989
+ Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [0.0000, 0.0000] })
990
+ Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [1.0000, 0.0000] })
991
+ Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [2.0000, 0.0000] })
992
+ Item 3: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [3.0000, 0.0000] })
993
+ Item 4: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [4.0000, 0.0000] })
994
+ Item 5: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [5.0000, 0.0000] })
995
+ "### ) ;
996
+
997
+ let mut wtxn = handle. env . write_txn ( ) . unwrap ( ) ;
998
+ let writer = Writer :: new ( handle. database , 0 , 2 ) ;
999
+
1000
+ // if we delete the 3 and 4 it should free the tree node 2
1001
+ writer. del_item ( & mut wtxn, 3 ) . unwrap ( ) ;
1002
+ writer. del_item ( & mut wtxn, 4 ) . unwrap ( ) ;
1003
+ writer. builder ( & mut rng) . n_trees ( 1 ) . build ( & mut wtxn) . unwrap ( ) ;
1004
+ wtxn. commit ( ) . unwrap ( ) ;
1005
+
1006
+ insta:: assert_snapshot!( handle, @r###"
1007
+ ==================
1008
+ Dumping index 0
1009
+ Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 5]>, roots: [0], distance: "euclidean" }
1010
+ Tree 0: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Item(0), right: Tree(4), normal: [1.0000, 0.0000] })
1011
+ Tree 1: Descendants(Descendants { descendants: [1, 5] })
1012
+ Tree 3: Descendants(Descendants { descendants: [2] })
1013
+ Tree 4: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(1), right: Tree(3), normal: [0.0000, 0.0000] })
1014
+ Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [0.0000, 0.0000] })
1015
+ Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [1.0000, 0.0000] })
1016
+ Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [2.0000, 0.0000] })
1017
+ Item 5: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [5.0000, 0.0000] })
1018
+ "### ) ;
1019
+
1020
+ let mut wtxn = handle. env . write_txn ( ) . unwrap ( ) ;
1021
+ let writer = Writer :: new ( handle. database , 0 , 2 ) ;
1022
+
1023
+ // if we re-insert both nodes, the id 2 should be re-used
1024
+ writer. add_item ( & mut wtxn, 3 , & [ 3. , 0. ] ) . unwrap ( ) ;
1025
+ writer. add_item ( & mut wtxn, 4 , & [ 4. , 0. ] ) . unwrap ( ) ;
1026
+ writer. builder ( & mut rng) . n_trees ( 1 ) . build ( & mut wtxn) . unwrap ( ) ;
1027
+ wtxn. commit ( ) . unwrap ( ) ;
1028
+
1029
+ insta:: assert_snapshot!( handle, @r###"
1030
+ ==================
1031
+ Dumping index 0
1032
+ Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0], distance: "euclidean" }
1033
+ Tree 0: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Item(0), right: Tree(4), normal: [1.0000, 0.0000] })
1034
+ Tree 1: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(2), right: Item(1), normal: [0.0000, 0.0000] })
1035
+ Tree 2: Descendants(Descendants { descendants: [4, 5] })
1036
+ Tree 3: Descendants(Descendants { descendants: [2, 3] })
1037
+ Tree 4: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(1), right: Tree(3), normal: [0.0000, 0.0000] })
984
1038
Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [0.0000, 0.0000] })
985
1039
Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [1.0000, 0.0000] })
986
1040
Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [2.0000, 0.0000] })
@@ -999,17 +1053,20 @@ fn reuse_node_id() {
999
1053
insta:: assert_snapshot!( handle, @r###"
1000
1054
==================
1001
1055
Dumping index 0
1002
- Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [4, 9], distance: "euclidean" }
1003
- Tree 0: Descendants(Descendants { descendants: [2, 3] })
1004
- Tree 1: Descendants(Descendants { descendants: [1, 3] })
1005
- Tree 2: Descendants(Descendants { descendants: [4, 5] })
1006
- Tree 3: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(5), right: Tree(2), normal: [0.0000, 0.0000] })
1007
- Tree 4: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Item(0), right: Tree(3), normal: [1.0000, 0.0000] })
1008
- Tree 5: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(0), right: Item(1), normal: [0.0000, 0.0000] })
1009
- Tree 6: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(1), right: Item(5), normal: [0.0000, 0.0000] })
1010
- Tree 7: Descendants(Descendants { descendants: [2, 4] })
1011
- Tree 8: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(6), right: Tree(7), normal: [0.0000, 0.0000] })
1012
- Tree 9: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(8), right: Item(0), normal: [-1.0000, 0.0000] })
1056
+ Root: Metadata { dimensions: 2, items: RoaringBitmap<[0, 1, 2, 3, 4, 5]>, roots: [0, 6], distance: "euclidean" }
1057
+ Tree 0: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Item(0), right: Tree(4), normal: [1.0000, 0.0000] })
1058
+ Tree 1: Descendants(Descendants { descendants: [5] })
1059
+ Tree 2: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(5), right: Item(1), normal: [0.0000, 0.0000] })
1060
+ Tree 3: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(2), right: Item(2), normal: [0.0000, 0.0000] })
1061
+ Tree 4: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(1), right: Tree(3), normal: [0.0000, 0.0000] })
1062
+ Tree 5: Descendants(Descendants { descendants: [3, 4] })
1063
+ Tree 6: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(12), right: Item(0), normal: [-1.0000, 0.0000] })
1064
+ Tree 7: Descendants(Descendants { descendants: [4, 5] })
1065
+ Tree 8: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Item(2), right: Tree(7), normal: [0.0000, 0.0000] })
1066
+ Tree 9: Descendants(Descendants { descendants: [] })
1067
+ Tree 10: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(8), right: Tree(9), normal: [0.0000, 0.0000] })
1068
+ Tree 11: Descendants(Descendants { descendants: [1, 3] })
1069
+ Tree 12: SplitPlaneNormal(SplitPlaneNormal<euclidean> { left: Tree(10), right: Tree(11), normal: [0.0000, 0.0000] })
1013
1070
Item 0: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [0.0000, 0.0000] })
1014
1071
Item 1: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [1.0000, 0.0000] })
1015
1072
Item 2: Leaf(Leaf { header: NodeHeaderEuclidean { bias: 0.0 }, vector: [2.0000, 0.0000] })
0 commit comments