BMDB stores its keys in byte-sorted order within a bucket. This makes sequential iteration over these keys extremely fast.
To iterate over a key prefix, we can use PrefixScanEntries function, and the parameters offsetNum and limitNum constrain the number of entries returned :
if err := db.View(
func(tx *bmdb.Tx) error {
prefix := []byte("user_")
bucket := "user_list"
// Constrain 100 entries returned
if keys, values, err := tx.PrefixScanEntries(bucket, prefix, "", 25, 100, true, true); err != nil {
return err
} else {
for k := range keys {
fmt.Println(string(keys[k]), string(values[k]))
}
}
return nil
}); err != nil {
log.Fatal(err)
}To iterate over a key prefix with search by regular expression on a second part of key without prefix, we can use PrefixScanEntries function when using the reg parameter,the parameters offsetNum, limitNum constrain the number of entries returned :
if err := db.View(
func(tx *bmdb.Tx) error {
prefix := []byte("user_")
reg := "username"
bucket := "user_list"
// Constrain 100 entries returned
if keys, values, err := tx.PrefixScanEntries(bucket, prefix, reg, 25, 100, true, true); err != nil {
return err
} else {
for k := range keys {
fmt.Println(string(keys[k]), string(values[k]))
}
}
return nil
}); err != nil {
log.Fatal(err)
}To scan over a range, we can use RangeScanEntries function. For example:
if err := db.View(
func(tx *bmdb.Tx) error {
// Assume key from user_0000000 to user_9999999.
// Query a specific user key range like this.
start := []byte("user_0010001")
end := []byte("user_0010010")
bucket := "user_list"
if keys, values, err := tx.RangeScanEntries(bucket, start, end, true, true); err != nil {
return err
} else {
for k := range keys {
fmt.Println(string(keys[k]), string(values[k]))
}
}
return nil
}); err != nil {
log.Fatal(err)
}To scan all keys and values of the bucket stored, we can use GetAll function. For example:
if err := db.View(
func(tx *bmdb.Tx) error {
bucket := "user_list"
entries, err := tx.GetAll(bucket)
if err != nil {
return err
}
for _, entry := range entries {
fmt.Println(string(entry.Key),string(entry.Value))
}
return nil
}); err != nil {
log.Println(err)
}The option parameter Reverse that determines whether the iterator is forward or Reverse. The current version does not support the iterator for HintBPTSparseIdxMode.
| Forward | Reverse |
|---|---|
tx, err := db.Begin(false)
iterator := bmdb.NewIterator(tx, bucket, bmdb.IteratorOptions{Reverse: false})
i := 0
for i < 10 {
ok, err := iterator.SetNext()
fmt.Println("ok, err", ok, err)
fmt.Println("Key: ", string(iterator.Entry().Key))
fmt.Println("Value: ", string(iterator.Entry().Value))
fmt.Println()
i++
}
err = tx.Commit()
if err != nil {
panic(err)
} |
tx, err := db.Begin(false)
iterator := bmdb.NewIterator(tx, bucket, bmdb.IteratorOptions{Reverse: true})
i := 0
for i < 10 {
ok, err := iterator.SetNext()
fmt.Println("ok, err", ok, err)
fmt.Println("Key: ", string(iterator.Entry().Key))
fmt.Println("Value: ", string(iterator.Entry().Value))
fmt.Println()
i++
}
err = tx.Commit()
if err != nil {
panic(err)
} |