Get values in key order

I’m trying to iterate over the db and basically get something after a certain point, but failing miserably. Follow me here for a moment.

If I do this:

package repository

import (
	"encoding/binary"
	"fmt"
	"github.com/dgraph-io/badger/v3"
	"testing"
)

func TestBadger(t *testing.T) {
	badgerOptions := badger.DefaultOptions("")
	badgerOptions.InMemory = true

	db, _ := badger.Open(badgerOptions)
	defer db.Close()

	db.Update(func(txn *badger.Txn) error {
		return txn.Set(key([]byte("abc"), "myid", 40, 1000), []byte("abc"))
	})

	db.Update(func(txn *badger.Txn) error {
		return txn.Set(key([]byte("abc"), "myid", 40, 500), []byte("abc"))
	})
	db.Update(func(txn *badger.Txn) error {
		return txn.Set(key([]byte("abc"), "myid", 40, 2000), []byte("abc"))
	})
	db.Update(func(txn *badger.Txn) error {
		return txn.Set(key([]byte("abc"), "myid", 40, 3000), []byte("abc"))
	})

	db.View(func(txn *badger.Txn) error {
		validPrefix := append([]byte("abc"), "|hello|"...)

		opt := badger.DefaultIteratorOptions
		opt.Prefix = validPrefix

		it := txn.NewIterator(opt)
		defer it.Close()

		for it.Seek(nil); it.ValidForPrefix(validPrefix); it.Next() {
			item := it.Item()

			err := item.Value(func(v []byte) error {
				fmt.Println(parseKey(item.Key()))
				return nil
			})
			if err != nil {
				panic(err)
			}
		}
		return nil
	})
}

func key(script []byte, id string, out uint64, height uint32) []byte {
	firstPart := append(script, "|hello|"...)

	secondPart := make([]byte, 4)
	binary.LittleEndian.PutUint32(secondPart, height)

	thirdPart := []byte(fmt.Sprintf("|%s|%d", id, out))

	key := append(firstPart, secondPart...)
	key = append(key, thirdPart...)

	return key
}

func parseKey(key []byte) string {
	script := key[:3]
	hello := key[3:10]
	height := binary.LittleEndian.Uint32(key[10:14])
	id := key[14:20]
	out := key[20:23]

	return fmt.Sprintf("%s%s%d%s%s\n", script, hello, height, id, out)
}

I get this:

abc|hello|3000|myid|40
abc|hello|2000|myid|40
abc|hello|1000|myid|40
abc|hello|500|myid|40

I was expecting to get in the order 500, 1000, 2000, 3000 in order, or at least on the order that I added? (1000, 500, 2000, 3000).

I tried some different strategies.

If I add opt.Reverse = true then I get nothing from the iterator.

If I try to use this:

height := make([]byte, 4)
binary.LittleEndian.PutUint32(height, 1000)

for it.Seek(append(validPrefix, height...)); it.ValidForPrefix(validPrefix); it.Next() {

I get this:

abc|hello|1000|myid|40
abc|hello|500|myid|40

Wait, I haven’t finished my attempts yet, if I do this:

opt.Reverse = true
height := make([]byte, 4)
binary.LittleEndian.PutUint32(height, 1000)

for it.Seek(append(validPrefix, height...)); it.ValidForPrefix(validPrefix); it.Next() {

Then I get this, which looks amazing:

abc|hello|2000|myid|40
abc|hello|3000|myid|40

Which kind make sense again, I’m reversing the order that was there, but then if I do this (height 1):

opt.Reverse = true
height := make([]byte, 4)
binary.LittleEndian.PutUint32(height, 1)

for it.Seek(append(validPrefix, height...)); it.ValidForPrefix(validPrefix); it.Next() {

Then I get nothing.

It’s mind blow :slight_smile:

Is there a way to get something in order or after a certain point?

Thanks