feat: add fuzzy search

This commit is contained in:
Henry
2025-10-01 23:13:22 +01:00
parent bd691017ad
commit f8475b77f1
6 changed files with 2818 additions and 6 deletions

View File

@@ -1,4 +1,4 @@
import { and, eq, ilike, inArray, isNull } from "drizzle-orm";
import { and, desc, eq, ilike, inArray, isNull, or, sql } from "drizzle-orm";
import type { dbClient } from "@kan/db/client";
import {
@@ -285,6 +285,7 @@ export const searchBoardsAndCards = async (
db: dbClient,
workspaceId: number,
query: string,
limit = 20,
) => {
const searchQuery = `%${query}%`;
@@ -295,15 +296,27 @@ export const searchBoardsAndCards = async (
title: boards.name,
description: boards.description,
slug: boards.slug,
updatedAt: boards.updatedAt,
createdAt: boards.createdAt,
})
.from(boards)
.where(
and(
eq(boards.workspaceId, workspaceId),
ilike(boards.name, searchQuery),
// Combine exact and fuzzy matching
or(
ilike(boards.name, `%${query}%`), // Exact substring match
sql`similarity(${boards.name}, ${query}) > 0.2`, // Fuzzy match
),
isNull(boards.deletedAt),
),
);
)
.orderBy(
sql`CASE WHEN ${boards.name} ILIKE ${`%${query}%`} THEN 1 ELSE 0 END DESC`,
sql`similarity(${boards.name}, ${query}) DESC`,
desc(boards.updatedAt),
)
.limit(Math.ceil(limit * 0.4));
// Search for cards
const cardResults = await db
@@ -314,6 +327,8 @@ export const searchBoardsAndCards = async (
boardPublicId: boards.publicId,
boardName: boards.name,
listName: lists.name,
updatedAt: cards.updatedAt,
createdAt: cards.createdAt,
})
.from(cards)
.innerJoin(lists, eq(cards.listId, lists.id))
@@ -321,12 +336,21 @@ export const searchBoardsAndCards = async (
.where(
and(
eq(boards.workspaceId, workspaceId),
ilike(cards.title, searchQuery),
or(
ilike(cards.title, searchQuery),
sql`similarity(${cards.title}, ${query}) > 0.2`,
),
isNull(cards.deletedAt),
isNull(lists.deletedAt),
isNull(boards.deletedAt),
),
);
)
.orderBy(
sql`CASE WHEN ${cards.title} ILIKE ${searchQuery} THEN 1 ELSE 0 END DESC`,
sql`similarity(${cards.title}, ${query}) DESC`,
desc(cards.updatedAt),
)
.limit(Math.floor(limit * 0.6));
// Combine results
const allResults = [
@@ -334,5 +358,6 @@ export const searchBoardsAndCards = async (
...cardResults.map((card) => ({ ...card, type: "card" as const })),
];
return allResults;
// Ensure we don't exceed the total limit
return allResults.slice(0, limit);
};