mirror of
https://github.com/docmost/docmost.git
synced 2026-08-25 15:57:11 +08:00
feat: add title-only search mode
Adds a titleOnly flag to page search: the Postgres driver matches titles via trigram-indexed unaccented LIKE ranked by word_similarity, and a Match filter in the search spotlight switches between everything and title-only matching.
This commit is contained in:
@@ -30,6 +30,10 @@ export class SearchDTO {
|
||||
@IsUUID('all', { each: true })
|
||||
labelIds?: string[];
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
titleOnly?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
limit?: number;
|
||||
|
||||
@@ -36,6 +36,21 @@ export class SearchService {
|
||||
}
|
||||
const searchQuery = tsquery(query.trim() + '*');
|
||||
const labelIds = [...new Set(searchParams.labelIds ?? [])];
|
||||
const titleOnly = searchParams.titleOnly === true;
|
||||
const titleQuery = query.trim();
|
||||
|
||||
const rankColumn = titleOnly
|
||||
? sql<number>`word_similarity(lower(f_unaccent(${titleQuery})), lower(f_unaccent(pages.title)))`.as(
|
||||
'rank',
|
||||
)
|
||||
: sql<number>`ts_rank(tsv, to_tsquery('english', f_unaccent(${searchQuery})))`.as(
|
||||
'rank',
|
||||
);
|
||||
const highlightColumn = titleOnly
|
||||
? sql<string>`''`.as('highlight')
|
||||
: sql<string>`ts_headline('english', text_content, to_tsquery('english', f_unaccent(${searchQuery})),'MinWords=9, MaxWords=10, MaxFragments=3')`.as(
|
||||
'highlight',
|
||||
);
|
||||
|
||||
let queryResults = this.db
|
||||
.selectFrom('pages')
|
||||
@@ -48,17 +63,24 @@ export class SearchService {
|
||||
'creatorId',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
sql<number>`ts_rank(tsv, to_tsquery('english', f_unaccent(${searchQuery})))`.as(
|
||||
'rank',
|
||||
),
|
||||
sql<string>`ts_headline('english', text_content, to_tsquery('english', f_unaccent(${searchQuery})),'MinWords=9, MaxWords=10, MaxFragments=3')`.as(
|
||||
'highlight',
|
||||
),
|
||||
rankColumn,
|
||||
highlightColumn,
|
||||
])
|
||||
.where(
|
||||
'tsv',
|
||||
'@@',
|
||||
sql<string>`to_tsquery('english', f_unaccent(${searchQuery}))`,
|
||||
.$if(!titleOnly, (qb) =>
|
||||
qb.where(
|
||||
'tsv',
|
||||
'@@',
|
||||
sql<string>`to_tsquery('english', f_unaccent(${searchQuery}))`,
|
||||
),
|
||||
)
|
||||
.$if(titleOnly, (qb) =>
|
||||
qb.where((eb) =>
|
||||
eb(
|
||||
sql`lower(f_unaccent(pages.title))`,
|
||||
'like',
|
||||
sql`lower(f_unaccent(${`%${titleQuery}%`}))`,
|
||||
),
|
||||
),
|
||||
)
|
||||
.$if(Boolean(searchParams.creatorId), (qb) =>
|
||||
qb.where('creatorId', '=', searchParams.creatorId),
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { type Kysely, sql } from 'kysely';
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await sql`CREATE INDEX IF NOT EXISTS pages_title_trgm_idx ON pages USING gin (lower(f_unaccent(title)) gin_trgm_ops)`.execute(
|
||||
db,
|
||||
);
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await sql`DROP INDEX IF EXISTS pages_title_trgm_idx`.execute(db);
|
||||
}
|
||||
+1
-1
Submodule apps/server/src/ee updated: 605c291e5b...641346a5b8
Reference in New Issue
Block a user