Skip to content

Commit 1f8a30d

Browse files
authored
Update README.md
looks cool
1 parent 78d627b commit 1f8a30d

File tree

1 file changed

+156
-50
lines changed

1 file changed

+156
-50
lines changed

README.md

Lines changed: 156 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,167 @@
1-
# Table
2-
Package table implements a memory efficient in-memory multicolumn string table aka multimap/bimap in golang
1+
# 📚 `table`
32

4-
# Example
3+
**A blazing-fast, memory-efficient multicolumn string table (multimap/bimap) for Go.**
4+
Store billions of rows in RAM, filter by multiple `(column → value)` clauses, and perform high-performance queries with optional “holes” for instant deletion performance.
5+
6+
---
7+
8+
## ✨ Features
9+
10+
✅ In-memory multicolumn string storage
11+
12+
✅ Supports duplicate rows, multi-key lookups, and range queries
13+
14+
✅ Explicit *holes* model for cheap deletes
15+
16+
✅ Manual compaction for full reuse of space
17+
18+
✅ Tiny memory footprint with optional quaternary filters
19+
20+
✅ Zero external dependencies except for `quaternary`
21+
22+
---
23+
24+
## 🚀 Quick Example
525

626
```go
727
package main
828

9-
import "github.com/neurlang/table"
10-
import "fmt"
11-
12-
var data = [][]string{
13-
{"play", "pièce", "obra"},
14-
{"cup", "tasse", "taza"},
15-
{"bank", "banque", "banco"},
16-
{"coin", "pièce", "moneda"},
17-
{"boat", "bateau", "barco"},
18-
{"cup", "verre", "copa"},
19-
{"earth", "terre", "tierra"},
20-
{"land", "terre", "tierra"},
21-
{"soap", "savon", "jabón"},
22-
{"ice", "glace", "hielo"},
23-
{"book", "livre", "libro"},
24-
{"room", "pièce", "habitación"},
25-
{"cup", "coupe", "copa"},
26-
{"glass", "verre", "copa"},
27-
{"pie", "gâteau", "tarta"},
28-
}
29+
import (
30+
"fmt"
31+
"github.com/neurlang/table"
32+
)
2933

3034
func main() {
31-
var table table.Table
32-
33-
// Insert initial data
34-
table.Insert(data)
35-
table.Compact()
36-
37-
// Do lookups
38-
fmt.Println(table.GetAll(0, "cup"))
39-
fmt.Println(table.GetAll(1, "terre"))
40-
fmt.Println(table.GetAll(2, "copa"))
41-
42-
// Insert something
43-
table.Insert([][]string{{"bench", "banc", "banco"}, {"faucet", "robinet", "llave"}, {"key", "clé", "llave"}})
44-
table.Compact()
45-
46-
// Do lookups on new data as well
47-
fmt.Println(table.GetAll(2, "banco"))
48-
fmt.Println(table.GetAll(2, "llave"))
49-
50-
// Deletion
51-
table.Remove(1, "verre")
52-
// No need to compact after deletions, only after insertions
53-
54-
// Do lookups
55-
fmt.Println(table.GetAll(0, "cup"))
35+
var t table.Table
36+
37+
// Insert rows
38+
data := [][]string{
39+
{"play", "pièce", "obra"},
40+
{"cup", "tasse", "taza"},
41+
{"bank", "banque", "banco"},
42+
{"coin", "pièce", "moneda"},
43+
{"boat", "bateau", "barco"},
44+
{"cup", "verre", "copa"},
45+
{"earth", "terre", "tierra"},
46+
{"land", "terre", "tierra"},
47+
{"soap", "savon", "jabón"},
48+
{"ice", "glace", "hielo"},
49+
{"book", "livre", "libro"},
50+
{"room", "pièce", "habitación"},
51+
{"cup", "coupe", "copa"},
52+
{"glass", "verre", "copa"},
53+
{"pie", "gâteau", "tarta"},
54+
}
55+
t.Insert(data)
56+
t.Compact()
57+
58+
// Query
59+
fmt.Println("Cups:", t.GetAll(0, "cup"))
60+
fmt.Println("terre:", t.GetAll(1, "terre"))
61+
fmt.Println("copa:", t.GetAll(2, "copa"))
62+
63+
// Insert more
64+
t.Insert([][]string{
65+
{"bench", "banc", "banco"},
66+
{"faucet", "robinet", "llave"},
67+
{"key", "clé", "llave"},
68+
})
69+
t.Compact()
70+
71+
fmt.Println("banco:", t.GetAll(2, "banco"))
72+
fmt.Println("llave:", t.GetAll(2, "llave"))
73+
74+
// Delete by value
75+
t.Remove(1, "verre")
76+
fmt.Println("Cups after delete:", t.GetAll(0, "cup"))
5677
}
5778
```
5879

59-
# Documentation
80+
---
81+
82+
## ⚙️ API Overview
83+
84+
| Method | Description | Direction |
85+
| ----------------------- | ------------------------------------------------------------------------------------- | --------- |
86+
| `Insert(rows)` | Insert rows. Holes are ignored. | Write |
87+
| `InsertHoles(rows)` | Insert rows as-is, including holes. | Write |
88+
| `Remove(col, val)` | Delete all rows where `col` equals `val`. Leaves holes for speed. | Write |
89+
| `DeleteBy(filters)` | Delete rows matching every `(col → val)`. Panics if filter is nil or empty. | Write |
90+
| `Get(col, val)` | Get one arbitrary row where `col` equals `val`. | Read |
91+
| `GetAll(col, val)` | Get all rows where `col` equals `val`. | Read |
92+
| `QueryBy(filters)` | Find all rows matching every `(col → val)`. Skips holes. Panics if filters nil/empty. | Read |
93+
| `QueryByHoles(filters)` | Same as `QueryBy` but includes holes. | Read |
94+
| `All()` | Return all rows, skipping holes. | Read |
95+
| `AllHoles()` | Return all rows including holes. | Read |
96+
| `Compact()` | Physically remove holes to reclaim RAM, rebuilds the quaternary indices. | Write |
97+
| `Count(col, val)` | Count number of times `val` appears in `col`. | Read |
98+
99+
---
100+
101+
## 🧹 Holes & Compaction
102+
103+
* **What’s a “hole”?**
104+
Deletions just nullify slots for speed. Rows with holes still take space.
105+
* **When to `Compact()`?**
106+
After bulk inserts or optionally after heavy deletes. Frequent compactions may hurt performance.
107+
* **Do I have to handle holes?**
108+
Use `QueryBy` and `All()` to skip holes. Use `QueryByHoles` and `AllHoles()` for raw physical view.
109+
110+
---
111+
112+
## ⚡️ Best Practices
113+
114+
* 🗝️ Use a consistent schema: same column count per row.
115+
* ⚠️ Never pass nil or empty filters to `QueryBy` or `DeleteBy` — they will panic!
116+
* 🧹 Run `Compact()` wisely — it’s not automatic.
117+
* 🚀 You can store millions of rows easily, but monitor RAM if you use `InsertHoles` a lot.
118+
* 🐛 Note: `GetAll` may return holes in some versions. Use `QueryBy` if you need strict correctness.
119+
120+
---
121+
122+
## 📏 Limitations
123+
124+
* No schema enforcement: you must keep row length consistent yourself.
125+
* No transactional batch operations.
126+
* No OR filter logic — `QueryBy` is always AND.
127+
* Panics on nil/empty filters — not error-safe by default.
128+
* It’s pure in-memory: no persistence, snapshot, or on-disk mode yet.
129+
* No mutex. Use mutex if threading, based on API call direction.
130+
131+
---
132+
133+
## 📚 Documentation
134+
135+
Full API reference: [pkg.go.dev](https://pkg.go.dev/github.com/neurlang/table)
136+
Issues and improvements: [GitHub Issues](https://github.com/neurlang/table/issues)
137+
138+
---
139+
140+
## 🔑 License
141+
142+
MIT — do anything you want. Attribution appreciated.
143+
144+
---
145+
146+
## 🙌 Contributing
147+
148+
We welcome improvements!
149+
File an issue for bug reports, feature requests, or performance tuning ideas.
150+
Large-scale fuzz tests, schema enforcement, and auto-compaction PRs are especially welcome.
151+
152+
---
153+
154+
## 🏁 Example Output
155+
156+
```shell
157+
[[cup tasse taza] [cup verre copa] [cup coupe copa]]
158+
[[earth terre tierra] [land terre tierra]]
159+
[[cup verre copa] [cup coupe copa] [glass verre copa]]
160+
[[bank banque banco] [bench banc banco]]
161+
[[faucet robinet llave] [key clé llave]]
162+
[[cup tasse taza] [cup coupe copa]]
163+
```
164+
165+
---
60166

61-
- [pkg.go.dev](https://pkg.go.dev/github.com/neurlang/table)
167+
## ❤️ Built for performance fanatics, by performance fanatics.

0 commit comments

Comments
 (0)