{"id":26930359,"url":"https://github.com/blobbybilb/gobble-db","last_synced_at":"2025-04-02T06:19:06.424Z","repository":{"id":230538223,"uuid":"779550120","full_name":"blobbybilb/gobble-db","owner":"blobbybilb","description":"Pure go (no cgo) \"struct-oriented\" on-disk embedded DB","archived":false,"fork":false,"pushed_at":"2024-06-14T18:05:34.000Z","size":618,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-07-11T12:49:42.351Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blobbybilb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-30T05:48:15.000Z","updated_at":"2024-06-14T18:05:37.000Z","dependencies_parsed_at":"2024-06-19T20:28:02.652Z","dependency_job_id":null,"html_url":"https://github.com/blobbybilb/gobble-db","commit_stats":null,"previous_names":["blobbybilb/gobble-db"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blobbybilb%2Fgobble-db","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blobbybilb%2Fgobble-db/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blobbybilb%2Fgobble-db/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blobbybilb%2Fgobble-db/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blobbybilb","download_url":"https://codeload.github.com/blobbybilb/gobble-db/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246763877,"owners_count":20829800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-02T06:19:05.661Z","updated_at":"2025-04-02T06:19:06.407Z","avatar_url":"https://github.com/blobbybilb.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gobble-db\n\nA pure go (no cgo) on-disk \"struct-oriented\" embedded DB, with a **simple**, **friendly**, and **general** API.\n\n#### Goal: friendliest simple embedded DB for small-to-medium-sized Go projects.\n\n**Simple**: 0 dependencies, entire API shown in the example below, ~800 LoC implementation\n\n**Friendly**: pure go so cross-compiling is easy, \"just works\" with no config, straightforward API\n\n**General**: simple doesn't mean limited, most functions take functions/types as params to allow for flexibility without\nthe added complexity of a query building API, relying instead on built-in Go language features and type system\n(see querying and indexing below).\n\n`go get github.com/blobbybilb/gobble-db`\n\n## Docs\n\nCore API Overview:\n```go\n// T is the type of the struct you want to store\nOpenCollection[T](db DB, name string)\ncollection.Insert(T)\ncollection.Select(func(T) bool) -\u003e []T // function param should return true for elements you want to retrieve\n\n// first function param should return true for elements you want\n// second function param should return the modified element\ncollection.Modify(func(T) bool, func(T) T)\n\ncollection.Delete(func(T) bool) // function param should return true for elements you want to delete\n\n// Indexing:\n\n// T is the type of the struct your collection holds, K is the type of the index\n// The function passed should return the value you want to index on, given a struct of type T\n// This gives you the flexibility to index on any field, part of a field, a combination of fields, etc.\nfunc OpenIndex[T, K](*Collection[T], func(T) K) -\u003e Index[T, K]\nindex.Get(K) -\u003e []T\n\n// (Note: most of these functions also return an error type, not shown here)\n```\n\nTake a look at this example covering all the functionality:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/blobbybilb/gobble-db\"\n)\n\n// Define your data type\n// Most structs containing data only would work, but they need to be serializable by the gob package\n// Gobble does not require you to do any gobble-specific configuration to your data types\ntype Shape struct {\n\tName        string\n\tNumSides    int\n\tSideLengths []int\n}\n\nfunc main() {\n\tdb, _ := gobble.OpenDB(\"test-db\")\n\n\t// Pass in your struct as a type parameter, now you have a collection of that struct\n\tshapes, _ := gobble.OpenCollection[Shape](db, \"shapes\")\n\n\t// Start inserting data\n\tshapes.Insert(Shape{\"Square\", 4, []int{4, 4, 4, 2}})\n\n\t// To query data, pass Select a function that takes in your struct and returns a boolean \u003c-- that's a \"query\" function\n\t// query: func(Shape) bool -\u003e ([]Shape, error)\n\tresult, _ := shapes.Select(func(shape Shape) bool { return shape.NumSides == 4 })\n\tfmt.Println(result) // result is a slice of Shape structs\n\n\t// To update data, pass Modify a query function,  and a function that takes in your struct and returns a modified struct \u003c-- that's an \"updater\" function\n\t// query: func(Shape) bool, updater: func(Shape) Shape\n\tshapes.Modify(\n\t\tfunc(shape Shape) bool { return shape.NumSides == 4 },\n\t\tfunc(shape Shape) Shape { shape.SideLengths[3] = 4; return shape })\n\n\t// To delete data, pass Delete a function that takes in your struct and returns a boolean\n\t// query: func(Shape) bool\n\tshapes.Delete(func(shape Shape) bool { return shape.NumSides \u003e 10 })\n\n\t// Indexing\n\t// Indexing speeds up querying by storing a hash map of keys to slices of structs in-memory, without an index queries need to scan the entire collection\n\t// Indexing does come with a memory and a (small) write performance cost, but read performance is greatly improved\n\t// Indexing is done by passing in a function that takes in your struct and returns a value to index on \u003c- that's an \"extractor\" function\n\t// The first type parameter is the type of the struct, and the second type parameter is the type of the index (in this case, string)\n\t// collection: *Collection[Shape], extractor: func(Shape) string -\u003e (Index[Shape, string], error)\n\tnameIndex, _ := gobble.OpenIndex[Shape, string](\u0026shapes, func(shape Shape) string { return shape.Name })\n\n\t// Now you can query the index by passing Get a value of the type that your extractor function returns (in this case, string)\n\t// key: string -\u003e ([]Shape, error)\n\tfmt.Println(nameIndex.Get(\"Square\"))\n\n\t// You can do more with indexes\n\t// This index has a key type of int (that represents the sum of the side lengths of the shape)\n\t// collection: *Collection[Shape], extractor: func(Shape) int -\u003e (Index[Shape, int], error)\n\tperimeterIndex, _ := gobble.OpenIndex[Shape, int](\u0026shapes, func(u Shape) int {\n\t\tsum := 0\n\t\tfor _, l := range u.SideLengths {\n\t\t\tsum += l\n\t\t}\n\t\treturn sum\n\t})\n\n\t// You can query it the same way, but with an int key\n\tperimeterIndex.Get(16)\n\n\t// Other functions\n\tshapes.Number()         // Returns the number of elements in the collection\n\tnameIndex.Num(\"Square\") // Returns the number of matching elements\n\tnameIndex.Del(\"Square\") // Deletes all elements that match the key\n\tnameIndex.Mod(\"Square\", // Modifies all elements that match the key, takes an updater function\n\t\tfunc(s Shape) Shape { s.Name = \"Still a Square\"; return s })\n}\n```\n\n\n## Info\n\n### Performance\n\nPerformance is not a priority; minimal development overhead is. That said, it should be fast enough for\nsmall-to-medium-sized projects (10k-100k items in a collection). Using some very rough benchmarks (like ~OoM):\n- Inserting 10k items takes about 1-2 seconds\n- Querying for ~5k of those takes about 0.5-1 seconds (not indexed)\n- Querying for ~5k of those takes about 0.1-0.2 seconds (indexed)\n- Querying for 1 of those takes about 0.00001-0.00003 seconds (indexed) (not indexed is about the same as for 5k not indexed)\n- Modifying 5k of those takes about 1-2 seconds (not indexed)\n- Deleting 5k of those takes about 0.5-1 seconds (not indexed)\n- Indexing 10k items takes about 1-1.5 seconds\n\n\n### Does it support transactions? Async I/O? ACID?\n\nNope. Too much complexity for the goal of this project.\n\n### Is it production ready?\nIf your \"production\" use case allows you to consider a library as new and not popular as this one,\nthen yes, it will probably be production-ready enough for your use case. It's meant to be simple enough\nthat any bugs surface quickly and are easy to fix.\n\n### Why is it called gobble-db?\nIt uses the Go \"gob\" binary data format, and it's supposed to be simple and friendly, so gobble-db.\n\n### License\nLGPLv2.1","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblobbybilb%2Fgobble-db","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblobbybilb%2Fgobble-db","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblobbybilb%2Fgobble-db/lists"}