### Install BuntDB Source: https://github.com/tidwall/buntdb/blob/master/README.md Installs the BuntDB library using go get. Ensure Go is installed. ```sh go get -u github.com/tidwall/buntdb ``` -------------------------------- ### Install BuntDB Benchmark Utility Source: https://github.com/tidwall/buntdb/blob/master/README.md Command to install the custom BuntDB benchmark utility using Go. ```bash go get github.com/tidwall/buntdb-benchmark ``` -------------------------------- ### Install Collate Package Source: https://github.com/tidwall/buntdb/blob/master/README.md Install the external `collate` package using `go get` to enable language-specific sorting for indexes. ```bash go get -u github.com/tidwall/collate ``` -------------------------------- ### Read and Set Database Configuration Source: https://github.com/tidwall/buntdb/blob/master/README.md Update BuntDB configuration by reading the current settings with `ReadConfig` and then applying modifications with `SetConfig`. This example shows how to read and then set the configuration. ```go var config buntdb.Config if err := db.ReadConfig(&config); err != nil{ log.Fatal(err) } if err := db.SetConfig(config); err != nil{ log.Fatal(err) } ``` -------------------------------- ### Create and Query JSON Indexes in BuntDB Source: https://github.com/tidwall/buntdb/blob/master/README.md This example demonstrates creating JSON indexes on specific fields (`name.last`, `age`) within JSON documents, populating the database, and then querying the data in ascending order by these indexed fields, including range queries. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") db.CreateIndex("last_name", "*", buntdb.IndexJSON("name.last")) db.CreateIndex("age", "*", buntdb.IndexJSON("age")) db.Update(func(tx *buntdb.Tx) error { tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil) tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil) tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil) tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil) return nil }) db.View(func(tx *buntdb.Tx) error { fmt.Println("Order by last name") tx.Ascend("last_name", func(key, value string) bool { fmt.Printf("%s: %s\n", key, value) return true }) fmt.Println("Order by age") tx.Ascend("age", func(key, value string) bool { fmt.Printf("%s: %s\n", key, value) return true }) fmt.Println("Order by age range 30-50") tx.AscendRange("age", `{"age":30}`, `{"age":50}`, func(key, value string) bool { fmt.Printf("%s: %s\n", key, value) return true }) return nil }) } ``` -------------------------------- ### Create and Query Multi-Value JSON Index in BuntDB Source: https://github.com/tidwall/buntdb/blob/master/README.md This example shows how to create a multi-value index on multiple JSON fields (`name.last`, `age`) to simulate a multi-column index. It then populates the database and iterates through the index to display the sorted results. ```go db, _ := buntdb.Open(":memory:") db.CreateIndex("last_name_age", "*", buntdb.IndexJSON("name.last"), buntdb.IndexJSON("age")) db.Update(func(tx *buntdb.Tx) error { tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil) tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil) tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil) tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil) tx.Set("5", `{"name":{"first":"Sam","last":"Anderson"},"age":51}`, nil) tx.Set("6", `{"name":{"first":"Melinda","last":"Prichard"},"age":44}`, nil) return nil }) db.View(func(tx *buntdb.Tx) error { tx.Ascend("last_name_age", func(key, value string) bool { fmt.Printf("%s: %s\n", key, value) return true }) return nil }) ``` -------------------------------- ### Create Descending Ordered Index Source: https://github.com/tidwall/buntdb/blob/master/README.md Use `buntdb.Desc` to wrap an index function for descending order. This example creates a multi-value index with ascending last name and descending age. ```go db.CreateIndex("last_name_age", "*", buntdb.IndexJSON("name.last"), buntdb.Desc(buntdb.IndexJSON("age")), ) ``` -------------------------------- ### Delete All Items and Get Length Source: https://context7.com/tidwall/buntdb/llms.txt Demonstrates how to remove all entries from a database using `DeleteAll` within a transaction and retrieve the total item count using `Len`. Useful for resetting the database. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Add some data db.Update(func(tx *buntdb.Tx) error { tx.Set("a", "1", nil) tx.Set("b", "2", nil) tx.Set("c", "3", nil) return nil }) // Get item count db.View(func(tx *buntdb.Tx) error { count, _ := tx.Len() fmt.Printf("Item count: %d\n", count) // Output: Item count: 3 return nil }) // Delete all items db.Update(func(tx *buntdb.Tx) error { return tx.DeleteAll() }) // Verify deletion db.View(func(tx *buntdb.Tx) error { count, _ := tx.Len() fmt.Printf("Item count after DeleteAll: %d\n", count) // Output: 0 return nil }) } ``` -------------------------------- ### Manage Key/Value Data Source: https://context7.com/tidwall/buntdb/llms.txt Use Set, Get, and Delete methods within transactions to manipulate database records. ```go package main import ( "fmt" "log" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Set values in a write transaction err := db.Update(func(tx *buntdb.Tx) error { tx.Set("name", "John Doe", nil) tx.Set("email", "john@example.com", nil) tx.Set("age", "30", nil) return nil }) if err != nil { log.Fatal(err) } // Get values in a read transaction err = db.View(func(tx *buntdb.Tx) error { name, _ := tx.Get("name") email, _ := tx.Get("email") age, _ := tx.Get("age") fmt.Printf("Name: %s, Email: %s, Age: %s\n", name, email, age) // Output: Name: John Doe, Email: john@example.com, Age: 30 return nil }) if err != nil { log.Fatal(err) } // Delete a value err = db.Update(func(tx *buntdb.Tx) error { val, err := tx.Delete("email") if err != nil { return err } fmt.Printf("Deleted: %s\n", val) // Output: Deleted: john@example.com return nil }) if err != nil { log.Fatal(err) } } ``` -------------------------------- ### BuntDB Benchmark Utility Results Source: https://github.com/tidwall/buntdb/blob/master/README.md Performance results from the custom BuntDB benchmark utility on a MacBook Pro. Shows operations per second for various operations like GET, SET, ASCEND, DESCEND, and SPATIAL operations. ```text $ buntdb-benchmark -q GET: 4609604.74 operations per second SET: 248500.33 operations per second ASCEND_100: 2268998.79 operations per second ASCEND_200: 1178388.14 operations per second ASCEND_400: 679134.20 operations per second ASCEND_800: 348445.55 operations per second DESCEND_100: 2313821.69 operations per second DESCEND_200: 1292738.38 operations per second DESCEND_400: 675258.76 operations per second DESCEND_800: 337481.67 operations per second SPATIAL_SET: 134824.60 operations per second SPATIAL_INTERSECTS_100: 939491.47 operations per second SPATIAL_INTERSECTS_200: 561590.40 operations per second SPATIAL_INTERSECTS_400: 306951.15 operations per second SPATIAL_INTERSECTS_800: 159673.91 operations per second ``` -------------------------------- ### Create Collation on JSON Index Source: https://github.com/tidwall/buntdb/blob/master/README.md Apply collation to JSON indexes using `collate.IndexJSON`. This example demonstrates Chinese case-insensitive sorting on a JSON field. ```go db.CreateIndex("last_name", "*", collate.IndexJSON("CHINESE_CI", "name.last")) ``` -------------------------------- ### Append-Only File Format Example Source: https://github.com/tidwall/buntdb/blob/master/README.md The append-only file (AOF) logs all database changes. This format shows sequential `set` and `del` operations. ```text set key:1 value1 set key:2 value2 set key:1 value3 del key:2 ... ``` -------------------------------- ### Get Value in BuntDB Transaction Source: https://github.com/tidwall/buntdb/blob/master/README.md Retrieves a value associated with a key within a read-only transaction. Returns ErrNotFound if the key does not exist. ```go err := db.View(func(tx *buntdb.Tx) error { val, err := tx.Get("mykey") if err != nil{ return err } fmt.Printf("value is %s\n", val) return nil }) ``` -------------------------------- ### Configure Database Settings in Go Source: https://context7.com/tidwall/buntdb/llms.txt Shows how to read and update database configuration, including sync policies and auto-shrink settings. ```go package main import ( "fmt" "log" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open("config_example.db") defer db.Close() // Read current configuration var config buntdb.Config if err := db.ReadConfig(&config); err != nil { log.Fatal(err) } // Modify configuration config.SyncPolicy = buntdb.Always // Sync after every write (safest) config.AutoShrinkPercentage = 50 // Shrink when AOF is 50% larger config.AutoShrinkMinSize = 16 * 1024 * 1024 // Minimum 16MB before auto-shrink config.AutoShrinkDisabled = false // Enable auto-shrinking // Optional: Handle expired keys with a callback config.OnExpired = func(keys []string) { for _, key := range keys { fmt.Printf("Key expired: %s\n", key) } } // Apply configuration if err := db.SetConfig(config); err != nil { log.Fatal(err) } fmt.Println("Configuration updated successfully") } ``` -------------------------------- ### Run Go Benchmarks Source: https://github.com/tidwall/buntdb/blob/master/README.md Execute the standard Go benchmark tool from the project root directory to measure BuntDB performance. ```bash go test --bench=. ``` -------------------------------- ### Open a BuntDB Database Source: https://context7.com/tidwall/buntdb/llms.txt Use the Open function to initialize a database. Pass a filename for persistent storage or ":memory:" for an in-memory instance. ```go package main import ( "log" "github.com/tidwall/buntdb" ) func main() { // Open a persistent database file (created if it doesn't exist) db, err := buntdb.Open("data.db") if err != nil { log.Fatal(err) } defer db.Close() // Or open a pure in-memory database (no disk persistence) memDB, err := buntdb.Open(":memory:") if err != nil { log.Fatal(err) } defer memDB.Close() } ``` -------------------------------- ### Manage Manual Transactions in Go Source: https://context7.com/tidwall/buntdb/llms.txt Demonstrates using Begin, Commit, and Rollback for fine-grained control over read and write transactions. ```go package main import ( "fmt" "log" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Manual read/write transaction tx, err := db.Begin(true) // true = writable if err != nil { log.Fatal(err) } tx.Set("key1", "value1", nil) tx.Set("key2", "value2", nil) // Commit the transaction if err := tx.Commit(); err != nil { log.Fatal(err) } // Manual read-only transaction tx, err = db.Begin(false) // false = read-only if err != nil { log.Fatal(err) } val, _ := tx.Get("key1") fmt.Printf("key1 = %s\n", val) // Read-only transactions must be rolled back tx.Rollback() // Demonstrate rollback tx, _ = db.Begin(true) tx.Set("key3", "value3", nil) tx.Rollback() // Changes are discarded // Verify key3 was not persisted db.View(func(tx *buntdb.Tx) error { _, err := tx.Get("key3") if err == buntdb.ErrNotFound { fmt.Println("key3 was rolled back") } return nil }) } ``` -------------------------------- ### Create Custom Indexes in Buntdb Source: https://context7.com/tidwall/buntdb/llms.txt Demonstrates creating custom indexes for string and numeric values using `CreateIndex`. Use this to efficiently sort and query data based on specific fields. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Create a case-insensitive string index for names db.CreateIndex("names", "user:*:name", buntdb.IndexString) // Create a numeric index for ages db.CreateIndex("ages", "user:*:age", buntdb.IndexInt) // Add data db.Update(func(tx *buntdb.Tx) error { tx.Set("user:1:name", "tom", nil) tx.Set("user:1:age", "35", nil) tx.Set("user:2:name", "Randi", nil) tx.Set("user:2:age", "49", nil) tx.Set("user:3:name", "jane", nil) tx.Set("user:3:age", "13", nil) tx.Set("user:4:name", "Paula", nil) tx.Set("user:4:age", "28", nil) return nil }) // Iterate by name (alphabetical, case-insensitive) fmt.Println("Sorted by name:") db.View(func(tx *buntdb.Tx) error { tx.Ascend("names", func(key, val string) bool { fmt.Printf(" %s: %s\n", key, val) return true }) return nil }) // Output: // user:3:name: jane // user:4:name: Paula // user:2:name: Randi // user:1:name: tom // Iterate by age (numeric order) fmt.Println("\nSorted by age:") db.View(func(tx *buntdb.Tx) error { tx.Ascend("ages", func(key, val string) bool { fmt.Printf(" %s: %s\n", key, val) return true }) return nil }) // Output: // user:3:age: 13 // user:4:age: 28 // user:1:age: 35 // user:2:age: 49 } ``` -------------------------------- ### Buntdb Pattern Matching Source: https://context7.com/tidwall/buntdb/llms.txt Illustrates how to use wildcard characters `*` and `?` for key filtering with `AscendKeys` and the `Match` function. Supports matching multiple keys based on defined patterns. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() db.Update(func(tx *buntdb.Tx) error { tx.Set("user:1:name", "Alice", nil) tx.Set("user:1:email", "alice@example.com", nil) tx.Set("user:2:name", "Bob", nil) tx.Set("user:2:email", "bob@example.com", nil) tx.Set("config:timeout", "30", nil) tx.Set("config:retries", "3", nil) return nil }) // Match all user names fmt.Println("User names (user:*:name):") db.View(func(tx *buntdb.Tx) error { tx.AscendKeys("user:*:name", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) // Match user 1's properties fmt.Println("\nUser 1 properties (user:1:*):") db.View(func(tx *buntdb.Tx) error { tx.AscendKeys("user:1:*", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) // Use Match function directly fmt.Println("\nDirect pattern matching:") fmt.Printf(" 'user:1:name' matches 'user:*:name': %v\n", buntdb.Match("user:1:name", "user:*:name")) fmt.Printf(" 'config:timeout' matches 'user:*': %v\n", buntdb.Match("config:timeout", "user:*")) } ``` -------------------------------- ### Create and Query Spatial Indexes in Go Source: https://context7.com/tidwall/buntdb/llms.txt Demonstrates creating an R-tree spatial index for 2D data and performing range and k-nearest neighbor queries. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Create a spatial index for fleet positions db.CreateSpatialIndex("fleet", "fleet:*:pos", buntdb.IndexRect) // Add lon,lat points using bracket syntax [lon lat] db.Update(func(tx *buntdb.Tx) error { tx.Set("fleet:0:pos", "[-115.567 33.532]", nil) // Vehicle 0 tx.Set("fleet:1:pos", "[-116.671 35.735]", nil) // Vehicle 1 tx.Set("fleet:2:pos", "[-113.902 31.234]", nil) // Vehicle 2 tx.Set("fleet:3:pos", "[-114.500 34.000]", nil) // Vehicle 3 return nil }) // Find all vehicles within a bounding box fmt.Println("Vehicles in bounding box [-117 30],[-112 36]:") db.View(func(tx *buntdb.Tx) error { tx.Intersects("fleet", "[-117 30],[-112 36]", func(key, val string) bool { fmt.Printf(" %s: %s\n", key, val) return true }) return nil }) // Find vehicles nearest to a point (k-nearest neighbors) fmt.Println("\nVehicles nearest to [-115 34]:") db.View(func(tx *buntdb.Tx) error { tx.Nearby("fleet", "[-115 34]", func(key, val string, dist float64) bool { fmt.Printf(" %s: %s (dist: %.2f)\n", key, val, dist) return true }) return nil }) } ``` -------------------------------- ### Iterate Keys in Buntdb Source: https://context7.com/tidwall/buntdb/llms.txt Demonstrates iterating over keys in ascending and descending order, as well as by pattern and range. Use these methods for ordered traversal and selective key retrieval. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Add some data db.Update(func(tx *buntdb.Tx) error { tx.Set("user:1", "Alice", nil) tx.Set("user:2", "Bob", nil) tx.Set("user:3", "Carol", nil) tx.Set("config:timeout", "30", nil) tx.Set("config:retries", "3", nil) return nil }) // Ascend through all keys fmt.Println("All keys (ascending):") db.View(func(tx *buntdb.Tx) error { tx.Ascend("", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true // continue iteration }) return nil }) // Descend through all keys fmt.Println("\nAll keys (descending):") db.View(func(tx *buntdb.Tx) error { tx.Descend("", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) // Iterate keys matching a pattern fmt.Println("\nUser keys only:") db.View(func(tx *buntdb.Tx) error { tx.AscendKeys("user:*", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) // Range iteration fmt.Println("\nRange user:1 to user:2:") db.View(func(tx *buntdb.Tx) error { tx.AscendRange("", "user:1", "user:3", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) } ``` -------------------------------- ### Perform Multi-Dimensional Spatial Queries in Go Source: https://context7.com/tidwall/buntdb/llms.txt Shows how to index and query data with up to 20 dimensions, including the use of infinity bounds for range queries. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Create spatial index for 3D points [X Y Timestamp] db.CreateSpatialIndex("points", "point:*", buntdb.IndexRect) // Add points with X, Y coordinates and timestamp db.Update(func(tx *buntdb.Tx) error { tx.Set("point:1", "[3 9 1]", nil) tx.Set("point:2", "[3 8 2]", nil) tx.Set("point:3", "[4 8 3]", nil) tx.Set("point:4", "[4 7 4]", nil) tx.Set("point:5", "[5 7 5]", nil) tx.Set("point:6", "[5 6 6]", nil) return nil }) // Query points with timestamp between 2 and 4 (using infinity for X,Y) fmt.Println("Points with timestamp 2-4:") db.View(func(tx *buntdb.Tx) error { tx.Intersects("points", "[-inf -inf 2],[+inf +inf 4]", func(key, val string) bool { fmt.Printf(" %s: %s\n", key, val) return true }) return nil }) // Output: // point:2: [3 8 2] // point:3: [4 8 3] // point:4: [4 7 4] } ``` -------------------------------- ### Save and Load Buntdb Snapshot Source: https://context7.com/tidwall/buntdb/llms.txt Saves the current database state to an io.Writer and loads it back into an in-memory database. Useful for creating backups or transferring data between in-memory instances. ```go package main import ( "bytes" "fmt" "log" "github.com/tidwall/buntdb" ) func main() { // Create and populate an in-memory database db1, _ := buntdb.Open(":memory:") db1.Update(func(tx *buntdb.Tx) error { tx.Set("user:1", "Alice", nil) tx.Set("user:2", "Bob", nil) tx.Set("user:3", "Carol", nil) return nil }) // Save snapshot to a buffer var buf bytes.Buffer if err := db1.Save(&buf); err != nil { log.Fatal(err) } db1.Close() fmt.Printf("Snapshot size: %d bytes\n", buf.Len()) // Load snapshot into a new in-memory database db2, _ := buntdb.Open(":memory:") defer db2.Close() if err := db2.Load(&buf); err != nil { log.Fatal(err) } // Verify data was restored db2.View(func(tx *buntdb.Tx) error { tx.Ascend("", func(key, value string) bool { fmt.Printf("Restored: %s = %s\n", key, value) return true }) return nil }) } ``` -------------------------------- ### Create a spatial index Source: https://github.com/tidwall/buntdb/blob/master/README.md Initialize an R-tree index for multi-dimensional data. ```go db.CreateSpatialIndex("fleet", "fleet:*:pos", buntdb.IndexRect) ``` -------------------------------- ### Create a custom string index Source: https://github.com/tidwall/buntdb/blob/master/README.md Define an index for ordering values using a pattern to filter keys. ```go db.CreateIndex("names", "*", buntdb.IndexString) ``` ```go db.CreateIndex("names", "user:*", buntdb.IndexString) ``` -------------------------------- ### Open a BuntDB Database Source: https://github.com/tidwall/buntdb/blob/master/README.md Opens a BuntDB database file. The file will be created if it does not exist. Use ":memory:" for an in-memory database without persistence. ```go package main import ( "log" "github.com/tidwall/buntdb" ) func main() { // Open the data.db file. It will be created if it doesn't exist. db, err := buntdb.Open("data.db") if err != nil { log.Fatal(err) } defer db.Close() ... } ``` ```go buntdb.Open(":memory:") // Open a file that does not persist to disk. ``` -------------------------------- ### Create Multi-Value Composite Indexes in Go Source: https://context7.com/tidwall/buntdb/llms.txt Combines multiple IndexJSON calls to create composite indexes, enabling SQL-like multi-column sorting behavior. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Create a multi-value index on last name and age db.CreateIndex("last_name_age", "*", buntdb.IndexJSON("name.last"), buntdb.IndexJSON("age"), ) // Add JSON documents db.Update(func(tx *buntdb.Tx) error { tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil) tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil) tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil) tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil) tx.Set("5", `{"name":{"first":"Sam","last":"Anderson"},"age":51}`, nil) tx.Set("6", `{"name":{"first":"Melinda","last":"Prichard"},"age":44}`, nil) return nil }) // Sorted by last name, then by age within same last name fmt.Println("Sorted by last name, then age:") db.View(func(tx *buntdb.Tx) error { tx.Ascend("last_name_age", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) // Output shows Anderson entries grouped (by age), Cooper, Johnson, Prichard (by age) } ``` -------------------------------- ### Set Data Expiration with TTL Source: https://github.com/tidwall/buntdb/blob/master/README.md Automatically evict items by setting a Time-To-Live (TTL) using `SetOptions`. The item will be deleted after the specified duration. ```go db.Update(func(tx *buntdb.Tx) error { tx.Set("mykey", "myval", &buntdb.SetOptions{Expires:true, TTL:time.Second}) return nil }) ``` -------------------------------- ### Create Collate i18n Indexes Source: https://github.com/tidwall/buntdb/blob/master/README.md Create indexes sorted by specified language using the `collate` package. Supports case-insensitive French sorting and numerical sorting with decimal points. ```go import "github.com/tidwall/collate" // To sort case-insensitive in French. db.CreateIndex("name", "*", collate.IndexString("FRENCH_CI")) // To specify that numbers should sort numerically ("2" < "12") // and use a comma to represent a decimal point. db.CreateIndex("amount", "*", collate.IndexString("FRENCH_NUM")) ``` -------------------------------- ### Iterate over database keys Source: https://github.com/tidwall/buntdb/blob/master/README.md Use Ascend to traverse keys in order within a read-only transaction. ```go err := db.View(func(tx *buntdb.Tx) error { err := tx.Ascend("", func(key, value string) bool { fmt.Printf("key: %s, value: %s\n", key, value) return true // continue iteration }) return err }) ``` -------------------------------- ### Create Descending Order Indexes in Go Source: https://context7.com/tidwall/buntdb/llms.txt Wraps index functions with buntdb.Desc to reverse the sort order for specific fields or composite index components. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Create a descending age index db.CreateIndex("ages_desc", "*", buntdb.Desc(buntdb.IndexJSON("age"))) // Create mixed: last name ascending, age descending db.CreateIndex("name_age_mixed", "*", buntdb.IndexJSON("name.last"), buntdb.Desc(buntdb.IndexJSON("age")), ) db.Update(func(tx *buntdb.Tx) error { tx.Set("1", `{"name":{"last":"Smith"},"age":30}`, nil) tx.Set("2", `{"name":{"last":"Smith"},"age":25}`, nil) tx.Set("3", `{"name":{"last":"Jones"},"age":40}`, nil) tx.Set("4", `{"name":{"last":"Jones"},"age":35}`, nil) return nil }) fmt.Println("Ages descending:") db.View(func(tx *buntdb.Tx) error { tx.Ascend("ages_desc", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) fmt.Println("\nName asc, age desc:") db.View(func(tx *buntdb.Tx) error { tx.Ascend("name_age_mixed", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) } ``` -------------------------------- ### Create a numeric index Source: https://github.com/tidwall/buntdb/blob/master/README.md Use built-in types like IndexInt for numerically ordered data. ```go db.CreateIndex("ages", "user:*:age", buntdb.IndexInt) ``` -------------------------------- ### Set Key with TTL in Buntdb Source: https://context7.com/tidwall/buntdb/llms.txt Sets a key with a specified Time-To-Live (TTL) expiration using `SetOptions`. Use this when you need keys to be automatically removed after a certain duration. ```go package main import ( "fmt" "time" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Set a key with 2-second TTL db.Update(func(tx *buntdb.Tx) error { tx.Set("session:abc123", "user_data", &buntdb.SetOptions{ Expires: true, TTL: 2 * time.Second, }) return nil }) // Check TTL remaining db.View(func(tx *buntdb.Tx) error { ttl, err := tx.TTL("session:abc123") if err != nil { return err } fmt.Printf("TTL remaining: %v\n", ttl) // Output: TTL remaining: ~2s return nil }) // Value is accessible immediately db.View(func(tx *buntdb.Tx) error { val, _ := tx.Get("session:abc123") fmt.Printf("Value: %s\n", val) // Output: Value: user_data return nil }) // Wait for expiration time.Sleep(3 * time.Second) // Value is now expired db.View(func(tx *buntdb.Tx) error { _, err := tx.Get("session:abc123") if err == buntdb.ErrNotFound { fmt.Println("Key has expired") // Output: Key has expired } return nil }) } ``` -------------------------------- ### Iterate over a custom index Source: https://github.com/tidwall/buntdb/blob/master/README.md Traverse the index to retrieve sorted values. ```go db.View(func(tx *buntdb.Tx) error { tx.Ascend("names", func(key, val string) bool { fmt.Printf(buf, "%s %s\n", key, val) return true }) return nil }) ``` -------------------------------- ### Read/write Transactions in BuntDB Source: https://github.com/tidwall/buntdb/blob/master/README.md Executes a read/write transaction. Only one read/write transaction can run at a time. All changes are persisted to disk upon successful completion. Returning an error will cause a rollback. ```go err := db.Update(func(tx *buntdb.Tx) error { // ... return nil }) ``` -------------------------------- ### Add numeric data Source: https://github.com/tidwall/buntdb/blob/master/README.md Set numeric values for indexing. ```go db.Update(func(tx *buntdb.Tx) error { tx.Set("user:0:age", "35", nil) tx.Set("user:1:age", "49", nil) tx.Set("user:2:age", "13", nil) tx.Set("user:4:age", "63", nil) tx.Set("user:5:age", "8", nil) tx.Set("user:6:age", "3", nil) tx.Set("user:7:age", "16", nil) return nil }) ``` -------------------------------- ### Add data to the database Source: https://github.com/tidwall/buntdb/blob/master/README.md Use Update to perform write operations within a transaction. ```go db.Update(func(tx *buntdb.Tx) error { tx.Set("user:0:name", "tom", nil) tx.Set("user:1:name", "Randi", nil) tx.Set("user:2:name", "jane", nil) tx.Set("user:4:name", "Janet", nil) tx.Set("user:5:name", "Paula", nil) tx.Set("user:6:name", "peter", nil) tx.Set("user:7:name", "Terri", nil) return nil }) ``` -------------------------------- ### Perform k-Nearest Neighbors Search in BuntDB Source: https://github.com/tidwall/buntdb/blob/master/README.md Use the `Nearby` function within a transaction to retrieve positions sorted by proximity. The callback function processes each result, and returning `true` continues the iteration. ```go db.View(func(tx *buntdb.Tx) error { tx.Nearby("fleet", "[-113 33]", func(key, val string, dist float64) bool { ... return true }) return nil }) ``` -------------------------------- ### Perform Read-Only Transactions with View Source: https://context7.com/tidwall/buntdb/llms.txt The View method allows concurrent read-only access to the database. Accessing non-existent keys returns buntdb.ErrNotFound. ```go package main import ( "fmt" "log" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // First, add some data db.Update(func(tx *buntdb.Tx) error { tx.Set("user:1", "Alice", nil) tx.Set("user:2", "Bob", nil) return nil }) // Read data within a read-only transaction err := db.View(func(tx *buntdb.Tx) error { val, err := tx.Get("user:1") if err != nil { return err } fmt.Printf("user:1 = %s\n", val) // Output: user:1 = Alice // Getting a non-existent key returns ErrNotFound _, err = tx.Get("user:999") if err == buntdb.ErrNotFound { fmt.Println("user:999 not found") } return nil }) if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Add spatial data Source: https://github.com/tidwall/buntdb/blob/master/README.md Store rectangle strings in the spatial index. ```go db.Update(func(tx *buntdb.Tx) error { tx.Set("fleet:0:pos", "[-115.567 33.532]", nil) tx.Set("fleet:1:pos", "[-116.671 35.735]", nil) tx.Set("fleet:2:pos", "[-113.902 31.234]", nil) return nil }) ``` -------------------------------- ### Shrink Buntdb Database Source: https://context7.com/tidwall/buntdb/llms.txt Manually compacts the append-only file by removing redundant log entries. Use this to reclaim disk space after many updates or deletes. Handles cases where shrink is already in progress. ```go package main import ( "fmt" "log" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open("shrink_example.db") defer db.Close() // Add and update many items (creates redundant log entries) for i := 0; i < 1000; i++ { db.Update(func(tx *buntdb.Tx) error { tx.Set("counter", fmt.Sprintf("%d", i), nil) return nil }) } // Manually trigger shrink to compact the AOF file if err := db.Shrink(); err != nil { if err == buntdb.ErrShrinkInProcess { fmt.Println("Shrink already in progress") } else { log.Fatal(err) } } else { fmt.Println("Database shrunk successfully") } } ``` -------------------------------- ### Iterate over a numeric index Source: https://github.com/tidwall/buntdb/blob/master/README.md Traverse the numeric index to retrieve sorted values. ```go db.View(func(tx *buntdb.Tx) error { tx.Ascend("ages", func(key, val string) bool { fmt.Printf(buf, "%s %s\n", key, val) return true }) return nil }) ``` -------------------------------- ### Perform Read/Write Transactions with Update Source: https://context7.com/tidwall/buntdb/llms.txt The Update method provides exclusive access for write operations. Changes are persisted upon successful completion of the transaction function. ```go package main import ( "fmt" "log" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() err := db.Update(func(tx *buntdb.Tx) error { // Set a new key-value pair previousValue, replaced, err := tx.Set("mykey", "myvalue", nil) if err != nil { return err } fmt.Printf("replaced: %v, previous: %s\n", replaced, previousValue) // Output: replaced: false, previous: // Update an existing key previousValue, replaced, err = tx.Set("mykey", "newvalue", nil) if err != nil { return err } fmt.Printf("replaced: %v, previous: %s\n", replaced, previousValue) // Output: replaced: true, previous: myvalue return nil }) if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Set Key/Value in BuntDB Transaction Source: https://github.com/tidwall/buntdb/blob/master/README.md Sets a key-value pair within a read/write transaction. The third argument can be used for options like TTL. ```go err := db.Update(func(tx *buntdb.Tx) error { _, _, err := tx.Set("mykey", "myvalue", nil) return err }) ``` -------------------------------- ### Create JSON Field Indexes in Go Source: https://context7.com/tidwall/buntdb/llms.txt Uses the IndexJSON function to index specific fields within JSON documents for efficient querying and range operations. ```go package main import ( "fmt" "github.com/tidwall/buntdb" ) func main() { db, _ := buntdb.Open(":memory:") defer db.Close() // Create indexes on JSON fields db.CreateIndex("last_name", "*", buntdb.IndexJSON("name.last")) db.CreateIndex("age", "*", buntdb.IndexJSON("age")) // Add JSON documents db.Update(func(tx *buntdb.Tx) error { tx.Set("1", `{"name":{"first":"Tom","last":"Johnson"},"age":38}`, nil) tx.Set("2", `{"name":{"first":"Janet","last":"Prichard"},"age":47}`, nil) tx.Set("3", `{"name":{"first":"Carol","last":"Anderson"},"age":52}`, nil) tx.Set("4", `{"name":{"first":"Alan","last":"Cooper"},"age":28}`, nil) return nil }) // Query by last name fmt.Println("Order by last name:") db.View(func(tx *buntdb.Tx) error { tx.Ascend("last_name", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) // Query by age fmt.Println("\nOrder by age:") db.View(func(tx *buntdb.Tx) error { tx.Ascend("age", func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) // Range query: ages 30-50 fmt.Println("\nAge range 30-50:") db.View(func(tx *buntdb.Tx) error { tx.AscendRange("age", `{"age":30}`, `{"age":50}`, func(key, value string) bool { fmt.Printf(" %s: %s\n", key, value) return true }) return nil }) } ``` -------------------------------- ### Read-only Transactions in BuntDB Source: https://github.com/tidwall/buntdb/blob/master/README.md Executes a read-only transaction. Multiple read-only transactions can run concurrently. Use this when no data modifications are needed. ```go err := db.View(func(tx *buntdb.Tx) error { // ... return nil }) ``` -------------------------------- ### Query a spatial index Source: https://github.com/tidwall/buntdb/blob/master/README.md Use Intersects to find data within a specific spatial range. ```go db.View(func(tx *buntdb.Tx) error { tx.Intersects("fleet", "[-117 30],[-112 36]", func(key, val string) bool { ... return true }) return nil }) ``` -------------------------------- ### Workaround for Deleting While Iterating Source: https://github.com/tidwall/buntdb/blob/master/README.md BuntDB does not support deleting keys during iteration. Collect keys to delete and process them after the iterator completes. ```go var delkeys []string tx.AscendKeys("object:*", func(k, v string) bool { if someCondition(k) == true { delkeys = append(delkeys, k) } return true // continue }) for _, k := range delkeys { if _, err = tx.Delete(k); err != nil { return err } } ``` -------------------------------- ### Search Spatial Data with Time Range in BuntDB Source: https://github.com/tidwall/buntdb/blob/master/README.md The `Intersects` function allows searching for data within a spatial and temporal range. It uses a callback to process matching records, printing the value of each match. ```go tx.Intersects("points", "[-inf -inf 2],[+inf +inf 4]", func(key, val string) bool { println(val) return true }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.