lucivy 4.0.1 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -4
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
-
# lucivy 4.0.
|
|
1
|
+
# lucivy 4.0.2
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**One index answers every question, and every answer is checked.** The default index answers exact substrings, matches across separators, typos across token boundaries, regular expressions and two-character needles — with BM25 and the exact bytes of every match — and nothing to configure per question; the ground-truth harness compares every answer to a scan of the files. From Node.js. Runs in your process, in your transaction (bring your own storage), and the same engine runs in the browser. Powered by Rust via napi-rs, MIT.
|
|
4
4
|
|
|
5
5
|
[**Try the live playground**](https://l-defraiteur.github.io/lucivy/) — runs entirely in your browser via WASM.
|
|
6
6
|
|
|
7
7
|
### What's new in 4.0.0
|
|
8
8
|
|
|
9
|
-
- **The index is 3.7× smaller** — the whole Linux kernel: 18 057 MB in 3.0.8, 4 938 MB in 4.0, 3 344 MB with `derivedInRam`; same answers, same spans, checked against the files ([the comparison with Elasticsearch and tantivy](
|
|
9
|
+
- **The index is 3.7× smaller** — the whole Linux kernel: 18 057 MB in 3.0.8, 4 938 MB in 4.0, 3 344 MB with `derivedInRam`; same answers, same spans, checked against the files ([the comparison with Elasticsearch and tantivy](https://github.com/L-Defraiteur/lucivy/blob/main/docs/compare-engines-2026-09-05.md))
|
|
10
10
|
- **The shared dictionary is the default** (`Index.create(path, fields, shards, false)` / `BlobIndex` option `sharedDictionary: false` keeps a suffix FST per segment: indexing ×1.5 faster, an index 23 % bigger) — one dictionary of token texts per shard instead of one per segment: 23 % smaller on the kernel, cold queries ×0.8-1.6, same answers; off by default, fixed at creation
|
|
11
11
|
- **`Index.create(path, fields, shards, sharedDictionary, derivedInRam, dictionaryWait)`** and **`BlobIndex` option `dictionaryWait`** — shared dictionary only: a commit returns before the shard's new texts are merged into the dictionary (a background task does it) and, by default, a search waits for that merge so that its cost never depends on when it runs; `false` searches at once over the not-yet-merged parts. Indexing with the dictionary costs ×1.5 (the kernel: 107 s against 56)
|
|
12
12
|
- **`Index.create(path, fields, shards, sharedDictionary, derivedInRam)`** and **`BlobIndex` option `derivedInRam`** — the three derived sidecars of each segment rebuilt byte for byte when the index opens instead of written: about a third less on disk, the open pays (the kernel: 2 s), never a query; off by default
|
|
13
13
|
- **Compatibility contract** — 4.0 opens a 3.0.x index and returns what 3.0.x returned (checked against a fixture the published 3.0.8 wheel built); 3.0.x does not open a 4.0 index; the first commit converts for good
|
|
14
14
|
|
|
15
|
+
### Against Elasticsearch and tantivy — one corpus, one truth
|
|
16
|
+
|
|
17
|
+
Same 93 983 Linux kernel files, 857 MB of text. Each engine is configured at its best for substring search, not at its default: Elasticsearch 8.19 with a trigram analyzer plus a `wildcard` field for regexes, tantivy 0.25 with its `NgramTokenizer`. The truth of every row is the same byte-by-byte scan of the files; a lucivy count is right only when its documents **and** its byte spans match it. On the substring itself all three agree to the document; where they part:
|
|
18
|
+
|
|
19
|
+
| asked | truth | lucivy | Elasticsearch | tantivy |
|
|
20
|
+
|---|---|---|---|---|
|
|
21
|
+
| `spin_lock`, separators relaxed (also `spin lock`, `spin-lock`, `spinlock`) | 9 552 | **9 552**, 23 ms | 6 577 — not with this analyzer: its trigrams carry the underscore | 6 601 — relaxed is the only mode it has: the separator never enters its index |
|
|
22
|
+
| `spinlokc`, two edits, across the token boundary | 10 034 | **10 034**, 148 ms | 3 549 — fuzziness compares whole terms | 6 557 — same |
|
|
23
|
+
| `spin_lock_[a-z]+`, a regex | 5 510 | **5 510**, 219 ms | 5 440 (wildcard field, 70 short), 480 ms | 0 — terms are already cut |
|
|
24
|
+
| `de`, two characters | 93 009 | **93 009**, 7.7 M spans, 561 ms | 0, silently | 0, silently |
|
|
25
|
+
| `retur -ENOMEM`, a fuzzy phrase | 14 449 | **14 449**, 30 ms | 14 446 (`span_near`), 24 ms — it does this well | — |
|
|
26
|
+
| **where it matched**: `mutex_lock`, 5 145 documents | 20 797 spans | **all 20 797, 15 ms** | `highlight` on the top 200: 179 ms | verifying 5 145 stored texts: 96 ms |
|
|
27
|
+
| your index **in your transaction** | — | **yes**: pluggable store, one commit for your rows and the index, rollback included | no: a server next to your database, a synchronisation to write | no: its own directory, its own commit |
|
|
28
|
+
| shards and nodes scoring **as one index**, as a library | — | **yes**, asserted by `test_federated_search` | yes, as a cluster | no: one index, one scale of scores |
|
|
29
|
+
|
|
30
|
+
Where a cell says "not with this analyzer", a purpose-built analyzer or plugin may get closer, at the price of designing it, configuring it and reindexing. Every question in the table is answered by lucivy's default index with nothing to configure, and each answer is checked. Sizes, indexing times and the full generated report: [docs/compare-engines-2026-09-05.md](https://github.com/L-Defraiteur/lucivy/blob/main/docs/compare-engines-2026-09-05.md); `benches/compare_engines.sh` replays it.
|
|
31
|
+
|
|
15
32
|
### What 3.0.0 brought
|
|
16
33
|
|
|
17
34
|
- **SFX v3 segment format** — per-field suffix FST files, the default for every new index; v2 indexes still open
|
|
@@ -26,7 +43,7 @@ Still there from 2.x: SFX-only engine, distributed search (`exportStats` / `merg
|
|
|
26
43
|
## Install
|
|
27
44
|
|
|
28
45
|
```bash
|
|
29
|
-
npm install lucivy # 4.0.
|
|
46
|
+
npm install lucivy # 4.0.2
|
|
30
47
|
```
|
|
31
48
|
|
|
32
49
|
## Quick start
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lucivy",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.2",
|
|
4
4
|
"description": "Fast BM25 full-text search with substring matching, fuzzy search, and regex — powered by Rust",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"build:debug": "napi build"
|
|
40
40
|
},
|
|
41
41
|
"optionalDependencies": {
|
|
42
|
-
"lucivy-linux-x64-gnu": "4.0.
|
|
43
|
-
"lucivy-linux-arm64-gnu": "4.0.
|
|
44
|
-
"lucivy-darwin-x64": "4.0.
|
|
45
|
-
"lucivy-darwin-arm64": "4.0.
|
|
46
|
-
"lucivy-windows-x64": "4.0.
|
|
42
|
+
"lucivy-linux-x64-gnu": "4.0.2",
|
|
43
|
+
"lucivy-linux-arm64-gnu": "4.0.2",
|
|
44
|
+
"lucivy-darwin-x64": "4.0.2",
|
|
45
|
+
"lucivy-darwin-arm64": "4.0.2",
|
|
46
|
+
"lucivy-windows-x64": "4.0.2"
|
|
47
47
|
}
|
|
48
48
|
}
|