lucivy 3.0.8 → 4.0.0

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.
Files changed (3) hide show
  1. package/README.md +24 -4
  2. package/index.d.ts +36 -3
  3. package/package.json +6 -6
package/README.md CHANGED
@@ -1,10 +1,18 @@
1
- # lucivy 3.0.8
1
+ # lucivy 4.0.0
2
2
 
3
- Fast BM25 full-text search for Node.js — with substring matching, fuzzy search, regex, and highlights. Powered by Rust via napi-rs.
3
+ Full-text search for code and technical text, as a library — from Node.js. Substrings, fuzzy and regex **across token boundaries**, BM25, exact byte spans, every answer checked against the files. 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
- ### What's new in 3.0.0
7
+ ### What's new in 4.0.0
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](../../docs/compare-engines-2026-09-05.md))
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
+ - **`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
+ - **`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
+ - **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
+
15
+ ### What 3.0.0 brought
8
16
 
9
17
  - **SFX v3 segment format** — per-field suffix FST files, the default for every new index; v2 indexes still open
10
18
  - **`parse` query type** — boolean syntax (`AND` / `OR` / `NOT`, quotes, `+` / `-`, parentheses) on top of substring matching
@@ -18,7 +26,7 @@ Still there from 2.x: SFX-only engine, distributed search (`exportStats` / `merg
18
26
  ## Install
19
27
 
20
28
  ```bash
21
- npm install lucivy@3.0.0
29
+ npm install lucivy # 4.0.0
22
30
  ```
23
31
 
24
32
  ## Quick start
@@ -55,6 +63,18 @@ const index = Index.create('/tmp/my_index', [
55
63
  // Sharded (4 shards)
56
64
  const sharded = Index.create('/tmp/sharded', [...], 4);
57
65
 
66
+ // Smaller index: one dictionary per shard instead of one per segment.
67
+ // About 20 % less disk and RAM; queries slightly slower at cold cache
68
+ // (roughly x1.2 to x1.6 on exact queries, fuzzy ones faster); same answers.
69
+ // Fixed at creation. (BlobIndex.create: `{ sharedDictionary: true }` in options.)
70
+ const compact = Index.create('/tmp/compact', [...], 1, true);
71
+
72
+ // Smaller still on disk: the three derived sidecars of each segment (about
73
+ // a third of the index) are rebuilt in RAM, byte for byte, when the index is
74
+ // opened, instead of being written. Same answers; opening pays the rebuild,
75
+ // never a query. (BlobIndex.create: `{ derivedInRam: true }`.)
76
+ const lean = Index.create('/tmp/lean', [...], 1, true, true);
77
+
58
78
  // Open existing
59
79
  const index2 = Index.open('/tmp/my_index');
60
80
  ```
package/index.d.ts CHANGED
@@ -83,6 +83,21 @@ export interface BlobIndexOptions {
83
83
  lazy?: boolean
84
84
  /** `create()` only: number of shards (default 1). */
85
85
  shards?: number
86
+ /**
87
+ * `create()` only: one dictionary per shard instead of one per segment
88
+ * (about 20 % smaller, slightly slower queries) — see `Index.create()`.
89
+ */
90
+ sharedDictionary?: boolean
91
+ /**
92
+ * `create()` only: the derived sidecars rebuilt in RAM at open instead
93
+ * of written (about a third smaller on disk) — see `Index.create()`.
94
+ */
95
+ derivedInRam?: boolean
96
+ /**
97
+ * `create()` only, shared dictionary: a search waits for the background
98
+ * merge of the last commit's texts (default `true`) — see `Index.create()`.
99
+ */
100
+ dictionaryWait?: boolean
86
101
  }
87
102
  export declare class Index {
88
103
  /**
@@ -92,8 +107,26 @@ export declare class Index {
92
107
  * @param fields - Field definitions: `[{name: "body", type: "text", stored: true}]`.
93
108
  * Types: `"text"` (full-text), `"u64"`, `"i64"`, `"f64"`, `"bool"`, `"date"`.
94
109
  * @param shards - Number of shards (default 1). More shards = faster search on large datasets.
95
- */
96
- static create(path: string, fields: Array<FieldDef>, shards?: number | undefined | null): Index
110
+ * @param sharedDictionary - Store each distinct token text once per shard
111
+ * instead of once per segment: the index is about 20 % smaller on disk
112
+ * and in RAM, queries are slightly slower at cold cache (roughly x1.2
113
+ * to x1.6 on exact queries, fuzzy ones faster) and a commit also writes
114
+ * the shard's new texts. Same answers either way. On by default since
115
+ * 4.0.0; `false` keeps a suffix FST per segment (indexing ×1.5 faster,
116
+ * an index 23 % bigger). Fixed at creation.
117
+ * @param derivedInRam - Do not write the three derived sidecars of each
118
+ * segment (`.posmap`, `.word_pos_map`, `.sibling_v3`, about a third
119
+ * of the index on disk); they are rebuilt in RAM, byte for byte, when
120
+ * the index is opened or reloaded. Same answers; opening pays the
121
+ * rebuild (never a query) and the rebuilt structures stay resident.
122
+ * Off by default; fixed at creation.
123
+ * @param dictionaryWait - Shared dictionary only. A commit returns before
124
+ * the shard's new texts are merged into the dictionary (a background
125
+ * task does it); a search waits for that merge, so that its cost never
126
+ * depends on when it runs. `false` searches at once over the
127
+ * not-yet-merged parts. On by default; fixed at creation.
128
+ */
129
+ static create(path: string, fields: Array<FieldDef>, shards?: number | undefined | null, sharedDictionary?: boolean | undefined | null, derivedInRam?: boolean | undefined | null, dictionaryWait?: boolean | undefined | null): Index
97
130
  /**
98
131
  * Open an existing index at the given path.
99
132
  *
@@ -404,7 +437,7 @@ export declare class BlobIndex {
404
437
  * @param store - Object implementing the store protocol (`load`, `save`, `delete`, `exists`, `list`, optional `blobLen` / `loadRange`).
405
438
  * @param indexName - Name of the index inside the store.
406
439
  * @param fields - Field definitions, as for `Index.create()`.
407
- * @param options - `{cacheDir?, lazy?, shards?}`.
440
+ * @param options - `{cacheDir?, lazy?, shards?, sharedDictionary?, derivedInRam?, dictionaryWait?}`.
408
441
  */
409
442
  static create(store: BlobStoreCallbacks, indexName: string, fields: Array<FieldDef>, options?: BlobIndexOptions | undefined | null): Promise<BlobIndex>
410
443
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucivy",
3
- "version": "3.0.8",
3
+ "version": "4.0.0",
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": "3.0.8",
43
- "lucivy-linux-arm64-gnu": "3.0.8",
44
- "lucivy-darwin-x64": "3.0.8",
45
- "lucivy-darwin-arm64": "3.0.8",
46
- "lucivy-windows-x64": "3.0.8"
42
+ "lucivy-linux-x64-gnu": "4.0.0",
43
+ "lucivy-linux-arm64-gnu": "4.0.0",
44
+ "lucivy-darwin-x64": "4.0.0",
45
+ "lucivy-darwin-arm64": "4.0.0",
46
+ "lucivy-windows-x64": "4.0.0"
47
47
  }
48
48
  }