Skip to content

Commit e025802

Browse files
committed
✨ add filter parameter to InvertedIndexMap.query
1 parent 4a98e54 commit e025802

2 files changed

Lines changed: 55 additions & 5 deletions

File tree

src/lang.spec.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,4 +1098,47 @@ describe("Lang.InvertedIndexMap", () => {
10981098
expect(productsIndex.query({ price: 599 }).length).toBe(0);
10991099
expect(productsIndex.query({ price: 499 }).length).toBe(1);
11001100
});
1101+
1102+
test("query with filter function", () => {
1103+
interface Product {
1104+
id: string;
1105+
category: string;
1106+
price: number;
1107+
stock: number;
1108+
}
1109+
1110+
const idx = new Lang.InvertedIndexMap<Product>(
1111+
(r) => r.id,
1112+
["category", "price"],
1113+
);
1114+
1115+
const products = [
1116+
{ id: "p1", category: "electronics", price: 100, stock: 5 },
1117+
{ id: "p2", category: "books", price: 20, stock: 10 },
1118+
{ id: "p3", category: "electronics", price: 200, stock: 3 },
1119+
{ id: "p4", category: "books", price: 15, stock: 8 },
1120+
];
1121+
1122+
products.forEach((p) => idx.add(p));
1123+
1124+
// Query with filter on indexed field + unindexed field filter
1125+
const results = idx.query({ category: "electronics" }, (p) => p.stock > 4);
1126+
expect(results).toEqual([products[0]]); // Only p1 matches both criteria
1127+
1128+
// Filter with no indexed query should work on all records
1129+
const highStock = idx.query({}, (p) => p.stock > 8);
1130+
expect(highStock).toEqual([products[1]]); // p2 has stock of 10
1131+
1132+
// Filter should run after indexed field filtering
1133+
const filteredBooks = idx.query({ category: "books" }, (p) => p.price < 20);
1134+
expect(filteredBooks).toEqual([products[3]]); // Only p4 matches
1135+
1136+
// Empty result if filter excludes all indexed matches
1137+
const noMatches = idx.query(
1138+
{ category: "electronics" },
1139+
(p) => p.stock > 10,
1140+
);
1141+
console.log("h4");
1142+
expect(noMatches).toEqual([]);
1143+
});
11011144
});

src/lang.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -796,18 +796,25 @@ export class InvertedIndexMap<R extends Record<keyof R, unknown>> {
796796
return sortedArrToIndexSet(intersected ?? []);
797797
}
798798

799-
query(q: Partial<R>): R[] {
799+
query(q: Partial<R>, filter?: (r: R) => boolean): R[] {
800800
const matched = this.queryIndexSet(q);
801801
if (matched.size === 0) {
802802
return [];
803803
}
804804
if (matched.size === this.data.length) {
805-
return this.data;
805+
if (!filter) {
806+
return this.data;
807+
} else {
808+
return this.data.filter(filter);
809+
}
806810
}
807-
const output: R[] = new Array(matched.size);
808-
let i = 0;
811+
const output: R[] = [];
809812
for (const idx of matched) {
810-
output[i++] = this.data[idx];
813+
const row = this.data[idx];
814+
if (filter && !filter(row)) {
815+
continue;
816+
}
817+
output.push(row);
811818
}
812819
return output;
813820
}

0 commit comments

Comments
 (0)