tidwall / buntdb

BuntDB is an embeddable, in-memory key/value database for Go with custom indexing and geospatial support
MIT License
4.57k stars 289 forks source link

Can't get AscendGreaterOrEqual to work. #20

Closed zippy closed 7 years ago

zippy commented 7 years ago

I have created an index with: db.CreateIndex("idx", "idx:*", buntdb.IndexInt) Then I set values with something like:

idx:=1
idxs := fmt.Sprintf("%d", idx)
_, _, err = tx.Set("idx:"+idxs, msg, nil)

Finally I try to retrieve values with:

since:= 1
err = dht.db.View(func(tx *buntdb.Tx) error {
    err = tx.AscendGreaterOrEqual("idx", string(since), func(key, value string) bool {
        log.Debugf("Got key:%s  and val:%s", key, value)
        return true
    })
    return err
})

if since = 1 or 0 then I get back all entries, but if since is > 1 I still get back all values! What am I doing wrong? Thanks! I.e. it doesn't actually seem to retrieve a subset.

tidwall commented 7 years ago

CreateIndex is used to create an index on the value, not the key.

With the operation tx.Set("idx:"+idxs, msg, nil) the msg will be the value that the index is ordered against.

In your case you are appending the idx to the key. Here's a full example using AscendGreaterOrEqual on the keys:

package main

import (
    "fmt"
    "math/rand"
    "strconv"

    "github.com/tidwall/buntdb"
)

func main() {
    db, _ := buntdb.Open(":memory:")
    // add 100 keys with the format 'key:001'
    db.Update(func(tx *buntdb.Tx) error {
        tx.CreateIndex("idx", "key:*", buntdb.IndexInt)
        for i := 0; i < 100; i++ {
            idx := strconv.Itoa(rand.Int() % 100)
            tx.Set(fmt.Sprintf("key:%03d", i), idx, nil)
        }
        return nil
    })
    // find all keys >= 'key:010'
    idx := 10
    db.View(func(tx *buntdb.Tx) error {
        tx.AscendGreaterOrEqual("", fmt.Sprintf("key:%03d", idx),
            func(key, val string) bool {
                keyidx, _ := strconv.Atoi(key[4:])
                fmt.Printf("%s %3d %3s\n", key, keyidx, val)
                return true
            },
        )
        return nil
    })
}

Here's an example using an index on the value:

package main

import (
    "fmt"
    "math/rand"
    "strconv"

    "github.com/tidwall/buntdb"
)

func main() {
    db, _ := buntdb.Open(":memory:")
    // add 100 keys with the format 'key:001'
    db.Update(func(tx *buntdb.Tx) error {
        tx.CreateIndex("idx", "key:*", buntdb.IndexInt)
        for i := 0; i < 100; i++ {
            idx := strconv.Itoa(rand.Int() % 100)
            tx.Set(fmt.Sprintf("key:%03d", i), idx, nil)
        }
        return nil
    })
    // find all values >= '10'
    idx := 10
    db.View(func(tx *buntdb.Tx) error {
        tx.AscendGreaterOrEqual("idx", strconv.Itoa(idx),
            func(key, val string) bool {
                keyidx, _ := strconv.Atoi(key[4:])
                fmt.Printf("%s %3d %3s\n", key, keyidx, val)
                return true
            },
        )
        return nil
    })
}

I hope these examples help.

tidwall commented 7 years ago

I'm closing this issue for now. Please feel free to reopen if you have further questions. Thanks.