@@ -476,6 +476,40 @@ func (db *DB) AscendKeys(pattern []byte, filterExpired bool, handleFn func(k []b
476476 })
477477}
478478
479+ // AscendKeysRange calls handleFn for keys within a range in the db in ascending order.
480+ // Since our expiry time is stored in the value, if you want to filter expired keys,
481+ // you need to set parameter filterExpired to true. But the performance will be affected.
482+ // Because we need to read the value of each key to determine if it is expired.
483+ func (db * DB ) AscendKeysRange (startKey , endKey , pattern []byte , filterExpired bool , handleFn func (k []byte ) (bool , error )) {
484+ db .mu .RLock ()
485+ defer db .mu .RUnlock ()
486+
487+ var reg * regexp.Regexp
488+ if len (pattern ) > 0 {
489+ reg = regexp .MustCompile (string (pattern ))
490+ }
491+
492+ db .index .AscendRange (startKey , endKey , func (key []byte , pos * wal.ChunkPosition ) (bool , error ) {
493+ if reg == nil || reg .Match (key ) {
494+ var invalid bool
495+ if filterExpired {
496+ chunk , err := db .dataFiles .Read (pos )
497+ if err != nil {
498+ return false , err
499+ }
500+ if value := db .checkValue (chunk ); value == nil {
501+ invalid = true
502+ }
503+ }
504+ if invalid {
505+ return true , nil
506+ }
507+ return handleFn (key )
508+ }
509+ return true , nil
510+ })
511+ }
512+
479513// Descend calls handleFn for each key/value pair in the db in descending order.
480514func (db * DB ) Descend (handleFn func (k []byte , v []byte ) (bool , error )) {
481515 db .mu .RLock ()
@@ -561,6 +595,40 @@ func (db *DB) DescendKeys(pattern []byte, filterExpired bool, handleFn func(k []
561595 })
562596}
563597
598+ // DescendKeysRange calls handleFn for keys within a range in the db in descending order.
599+ // Since our expiry time is stored in the value, if you want to filter expired keys,
600+ // you need to set parameter filterExpired to true. But the performance will be affected.
601+ // Because we need to read the value of each key to determine if it is expired.
602+ func (db * DB ) DescendKeysRange (startKey , endKey , pattern []byte , filterExpired bool , handleFn func (k []byte ) (bool , error )) {
603+ db .mu .RLock ()
604+ defer db .mu .RUnlock ()
605+
606+ var reg * regexp.Regexp
607+ if len (pattern ) > 0 {
608+ reg = regexp .MustCompile (string (pattern ))
609+ }
610+
611+ db .index .DescendRange (startKey , endKey , func (key []byte , pos * wal.ChunkPosition ) (bool , error ) {
612+ if reg == nil || reg .Match (key ) {
613+ var invalid bool
614+ if filterExpired {
615+ chunk , err := db .dataFiles .Read (pos )
616+ if err != nil {
617+ return false , err
618+ }
619+ if value := db .checkValue (chunk ); value == nil {
620+ invalid = true
621+ }
622+ }
623+ if invalid {
624+ return true , nil
625+ }
626+ return handleFn (key )
627+ }
628+ return true , nil
629+ })
630+ }
631+
564632func (db * DB ) checkValue (chunk []byte ) []byte {
565633 record := decodeLogRecord (chunk )
566634 now := time .Now ().UnixNano ()
0 commit comments