@devisfuture/mega-collection 1.1.2 → 1.1.5
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 +10 -11
- package/dist/chunk-2OBCQ7TF.mjs +1 -0
- package/dist/index.mjs +1 -1
- package/dist/search/index.d.mts +0 -4
- package/dist/search/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-VSCCECO2.mjs +0 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
What does this package solve?
|
|
12
12
|
|
|
13
|
-
Sometimes in projects, you need to iterate through huge collections (
|
|
13
|
+
Sometimes in projects, you need to iterate through huge collections (100K+ elements in an array) that have come from the server. Usually, the most common features are searching, filtering, and sorting.
|
|
14
14
|
So, this package helps to perform searching, filtering, and sorting of large collections faster than standard JavaScript methods. This operation is performed before rendering the UI content.
|
|
15
15
|
|
|
16
16
|
Zero dependencies. Tree-shakeable. Import only what you need.
|
|
@@ -83,7 +83,7 @@ const engine = new MergeEngines<User>({
|
|
|
83
83
|
// dataset is passed once at init — no need to repeat it in every call
|
|
84
84
|
engine.search("john");
|
|
85
85
|
engine.sort([{ field: "age", direction: "asc" }]);
|
|
86
|
-
engine.filter([{ field: "city", values: ["
|
|
86
|
+
engine.filter([{ field: "city", values: ["Miami", "New York"] }]);
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
---
|
|
@@ -102,13 +102,12 @@ const engine = new TextSearchEngine<User>({
|
|
|
102
102
|
minQueryLength: 2, // begins searching when query length >= 2
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
// note: inputs shorter than `minQueryLength`
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
// result so the UI doesn’t flush on every keystroke.
|
|
105
|
+
// note: inputs shorter than `minQueryLength` bypass the indexed search and
|
|
106
|
+
// simply return the original dataset (rather than clearing the result).
|
|
107
|
+
// A one‑character search usually matches most of the dataset, so avoiding
|
|
108
|
+
// extra work makes typing feel snappier. Once the query reaches the
|
|
109
|
+
// threshold the indexed search kicks in and performance improves
|
|
110
|
+
// dramatically. Empty/blank queries still return an empty array.
|
|
112
111
|
|
|
113
112
|
engine.search("john"); // searches all indexed fields, deduplicated
|
|
114
113
|
engine.search("name", "john"); // searches a specific field
|
|
@@ -130,13 +129,13 @@ const engine = new FilterEngine<User>({
|
|
|
130
129
|
});
|
|
131
130
|
|
|
132
131
|
engine.filter([
|
|
133
|
-
{ field: "city", values: ["
|
|
132
|
+
{ field: "city", values: ["Miami", "New York"] },
|
|
134
133
|
{ field: "age", values: [25, 30, 35] },
|
|
135
134
|
]);
|
|
136
135
|
|
|
137
136
|
// Sequential mode example:
|
|
138
137
|
// 1) First call filters by city
|
|
139
|
-
const byCity = engine.filter([{ field: "city", values: ["
|
|
138
|
+
const byCity = engine.filter([{ field: "city", values: ["Miami"] }]);
|
|
140
139
|
// 2) Second call filters only inside previous result
|
|
141
140
|
const byCityAndAge = engine.filter([{ field: "age", values: [22] }]);
|
|
142
141
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var T=3,f=12;function x(h){let t=h.toLowerCase(),n=Math.min(T,t.length),e=t.length-n+1,r=new Array(e);for(let s=0;s<e;s++)r[s]=t.substring(s,s+n);return r}function m(h){let t=x(h);if(t.length<=f)return new Set(t);let n=new Set,e=t.length-1,r=f-1;for(let s=0;s<=r;s++){let i=Math.round(s*e/r);n.add(t[i]);}return n}function L(h,t){let n=h.get(t);if(n)return n;let e=new Set;return h.set(t,e),e}var y=class{constructor(t={}){this.ngramIndexes=new Map;this.data=[];if(this.minQueryLength=t.minQueryLength??1,!!t.data&&(this.data=t.data,!!t.fields?.length))for(let n of t.fields)this.buildIndex(t.data,n);}buildIndex(t,n){let e,r;if(Array.isArray(t))e=t,r=n;else {if(!this.data.length)throw new Error("TextSearchEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).");e=this.data,r=t;}this.data=e;let s=new Map;for(let i=0,d=e.length;i<d;i++){let l=e[i][r];if(typeof l!="string")continue;let o=l.toLowerCase();for(let a=0,u=o.length;a<u;a++){let g=u-a,p=Math.min(T,g);for(let c=1;c<=p;c++){let I=o.substring(a,a+c);L(s,I).add(i);}}}return this.ngramIndexes.set(r,s),this}search(t,n){return n===void 0?this.searchAllFields(t):this.searchField(t,n)}normalizeQuery(t){return t.trim().toLowerCase()}searchAllFields(t){let n=[...this.ngramIndexes.keys()],e=this.normalizeQuery(t);if(!e)return [];if(e.length<this.minQueryLength)return this.data;if(!n.length)return this.searchAllFieldsLinear(e);let r=m(e);if(!r.size)return [];let s=new Set,i=[];for(let d of n)for(let l of this.searchFieldWithPreparedQuery(d,e,r))s.has(l)||(s.add(l),i.push(l));return i}searchField(t,n){let e=this.normalizeQuery(n);if(!e)return [];if(e.length<this.minQueryLength)return this.data;if(!this.ngramIndexes.size)return this.searchFieldLinear(t,e);let r=m(e);return r.size?this.searchFieldWithPreparedQuery(t,e,r):[]}searchFieldWithPreparedQuery(t,n,e){let r=this.ngramIndexes.get(t);if(!r)return [];let s=[];for(let o of e){let a=r.get(o);if(!a)return [];s.push(a);}s.sort((o,a)=>o.size-a.size);let i=s[0],d=s.length,l=[];for(let o of i){let a=true;for(let g=1;g<d;g++)if(!s[g].has(o)){a=false;break}if(!a)continue;let u=this.data[o][t];typeof u=="string"&&u.toLowerCase().includes(n)&&l.push(this.data[o]);}return l}searchAllFieldsLinear(t){if(!this.data.length)return [];let n=[];for(let e=0;e<this.data.length;e++){let r=this.data[e],s=false;for(let i of Object.values(r))if(typeof i=="string"&&i.toLowerCase().includes(t)){s=true;break}s&&n.push(r);}return n}searchFieldLinear(t,n){if(!this.data.length)return [];let e=[];for(let r=0;r<this.data.length;r++){let s=this.data[r][t];typeof s=="string"&&s.toLowerCase().includes(n)&&e.push(this.data[r]);}return e}clear(){this.ngramIndexes.clear(),this.data=[];}};export{y as a};
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{a as TextSearchEngine}from'./chunk-
|
|
1
|
+
export{a as TextSearchEngine}from'./chunk-2OBCQ7TF.mjs';export{a as FilterEngine}from'./chunk-XFQ56UZU.mjs';export{a as SortEngine}from'./chunk-DBAABXBP.mjs';export{a as MergeEngines}from'./chunk-KMSFPZKF.mjs';
|
package/dist/search/index.d.mts
CHANGED
|
@@ -26,10 +26,6 @@ declare class TextSearchEngine<T extends CollectionItem> {
|
|
|
26
26
|
search(query: string): T[];
|
|
27
27
|
search(field: keyof T & string, query: string): T[];
|
|
28
28
|
private normalizeQuery;
|
|
29
|
-
/**
|
|
30
|
-
* Checks if the query is long enough to search.
|
|
31
|
-
*/
|
|
32
|
-
private isQuerySearchable;
|
|
33
29
|
/**
|
|
34
30
|
* Searches all indexed fields.
|
|
35
31
|
*/
|
package/dist/search/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{a as TextSearchEngine}from'../chunk-
|
|
1
|
+
export{a as TextSearchEngine}from'../chunk-2OBCQ7TF.mjs';
|
package/package.json
CHANGED
package/dist/chunk-VSCCECO2.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var T=3,f=12;function x(h){let e=h.toLowerCase(),n=Math.min(T,e.length),t=e.length-n+1,r=new Array(t);for(let s=0;s<t;s++)r[s]=e.substring(s,s+n);return r}function m(h){let e=x(h);if(e.length<=f)return new Set(e);let n=new Set,t=e.length-1,r=f-1;for(let s=0;s<=r;s++){let i=Math.round(s*t/r);n.add(e[i]);}return n}function L(h,e){let n=h.get(e);if(n)return n;let t=new Set;return h.set(e,t),t}var y=class{constructor(e={}){this.ngramIndexes=new Map;this.data=[];if(this.minQueryLength=e.minQueryLength??1,!!e.data&&(this.data=e.data,!!e.fields?.length))for(let n of e.fields)this.buildIndex(e.data,n);}buildIndex(e,n){let t,r;if(Array.isArray(e))t=e,r=n;else {if(!this.data.length)throw new Error("TextSearchEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).");t=this.data,r=e;}this.data=t;let s=new Map;for(let i=0,u=t.length;i<u;i++){let l=t[i][r];if(typeof l!="string")continue;let o=l.toLowerCase();for(let a=0,d=o.length;a<d;a++){let c=d-a,p=Math.min(T,c);for(let g=1;g<=p;g++){let I=o.substring(a,a+g);L(s,I).add(i);}}}return this.ngramIndexes.set(r,s),this}search(e,n){return n===void 0?this.searchAllFields(e):this.searchField(e,n)}normalizeQuery(e){return e.trim().toLowerCase()}isQuerySearchable(e){return !(!e||e.length<this.minQueryLength)}searchAllFields(e){let n=[...this.ngramIndexes.keys()],t=this.normalizeQuery(e);if(!this.isQuerySearchable(t))return [];if(!n.length)return this.searchAllFieldsLinear(t);let r=m(t);if(!r.size)return [];let s=new Set,i=[];for(let u of n)for(let l of this.searchFieldWithPreparedQuery(u,t,r))s.has(l)||(s.add(l),i.push(l));return i}searchField(e,n){let t=this.normalizeQuery(n);if(!this.isQuerySearchable(t))return [];if(!this.ngramIndexes.size)return this.searchFieldLinear(e,t);let r=m(t);return r.size?this.searchFieldWithPreparedQuery(e,t,r):[]}searchFieldWithPreparedQuery(e,n,t){let r=this.ngramIndexes.get(e);if(!r)return [];let s=[];for(let o of t){let a=r.get(o);if(!a)return [];s.push(a);}s.sort((o,a)=>o.size-a.size);let i=s[0],u=s.length,l=[];for(let o of i){let a=true;for(let c=1;c<u;c++)if(!s[c].has(o)){a=false;break}if(!a)continue;let d=this.data[o][e];typeof d=="string"&&d.toLowerCase().includes(n)&&l.push(this.data[o]);}return l}searchAllFieldsLinear(e){if(!this.data.length)return [];let n=[];for(let t=0;t<this.data.length;t++){let r=this.data[t],s=false;for(let i of Object.values(r))if(typeof i=="string"&&i.toLowerCase().includes(e)){s=true;break}s&&n.push(r);}return n}searchFieldLinear(e,n){if(!this.data.length)return [];let t=[];for(let r=0;r<this.data.length;r++){let s=this.data[r][e];typeof s=="string"&&s.toLowerCase().includes(n)&&t.push(this.data[r]);}return t}clear(){this.ngramIndexes.clear(),this.data=[];}};export{y as a};
|