mirror of
https://github.com/docmost/docmost.git
synced 2025-11-19 14:41:10 +10:00
Refactoring
* replace TypeORM with Kysely query builder * refactor migrations * other changes and fixes
This commit is contained in:
@ -4,6 +4,8 @@ export class SearchResponseDto {
|
||||
icon: string;
|
||||
parentPageId: string;
|
||||
creatorId: string;
|
||||
rank: string;
|
||||
rank: number;
|
||||
highlight: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
@ -10,8 +10,8 @@ import {
|
||||
import { SearchService } from './search.service';
|
||||
import { SearchDTO } from './dto/search.dto';
|
||||
import { AuthWorkspace } from '../../decorators/auth-workspace.decorator';
|
||||
import { Workspace } from '../workspace/entities/workspace.entity';
|
||||
import { JwtAuthGuard } from '../../guards/jwt-auth.guard';
|
||||
import { Workspace } from '@docmost/db/types/entity.types';
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Controller('search')
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { SearchController } from './search.controller';
|
||||
import { SearchService } from './search.service';
|
||||
import { PageModule } from '../page/page.module';
|
||||
|
||||
@Module({
|
||||
imports: [PageModule],
|
||||
controllers: [SearchController],
|
||||
providers: [SearchService],
|
||||
})
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PageRepository } from '../page/repositories/page.repository';
|
||||
import { SearchDTO } from './dto/search.dto';
|
||||
import { SearchResponseDto } from './dto/search-response.dto';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { KyselyDB } from '@docmost/db/types/kysely.types';
|
||||
import { sql } from 'kysely';
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const tsquery = require('pg-tsquery')();
|
||||
|
||||
@Injectable()
|
||||
export class SearchService {
|
||||
constructor(private pageRepository: PageRepository) {}
|
||||
constructor(@InjectKysely() private readonly db: KyselyDB) {}
|
||||
|
||||
async searchPage(
|
||||
query: string,
|
||||
@ -19,46 +21,32 @@ export class SearchService {
|
||||
}
|
||||
const searchQuery = tsquery(query.trim() + '*');
|
||||
|
||||
const selectColumns = [
|
||||
'page.id as id',
|
||||
'page.title as title',
|
||||
'page.icon as icon',
|
||||
'page.parentPageId as "parentPageId"',
|
||||
'page.creatorId as "creatorId"',
|
||||
'page.createdAt as "createdAt"',
|
||||
'page.updatedAt as "updatedAt"',
|
||||
];
|
||||
|
||||
const searchQueryBuilder = await this.pageRepository
|
||||
.createQueryBuilder('page')
|
||||
.select(selectColumns);
|
||||
|
||||
searchQueryBuilder.andWhere('page.workspaceId = :workspaceId', {
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
searchQueryBuilder
|
||||
.addSelect('ts_rank(page.tsv, to_tsquery(:searchQuery))', 'rank')
|
||||
.addSelect(
|
||||
`ts_headline('english', page.textContent, to_tsquery(:searchQuery), 'MinWords=9, MaxWords=10, MaxFragments=10')`,
|
||||
'highlight',
|
||||
const queryResults = await this.db
|
||||
.selectFrom('pages')
|
||||
.select([
|
||||
'id',
|
||||
'title',
|
||||
'icon',
|
||||
'parentPageId',
|
||||
'creatorId',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
sql<number>`ts_rank(tsv, to_ts_query(${searchQuery}))`.as('rank'),
|
||||
sql<string>`ts_headline('english', page.textContent, to_tsquery(${searchQuery}), 'MinWords=9, MaxWords=10, MaxFragments=10')`.as(
|
||||
'highlight',
|
||||
),
|
||||
])
|
||||
.where('workspaceId', '=', workspaceId)
|
||||
.where('tsv', '@@', sql<string>`to_tsquery(${searchQuery})`)
|
||||
.$if(Boolean(searchParams.creatorId), (qb) =>
|
||||
qb.where('creatorId', '=', searchParams.creatorId),
|
||||
)
|
||||
.andWhere('page.tsv @@ to_tsquery(:searchQuery)', { searchQuery })
|
||||
.orderBy('rank', 'DESC');
|
||||
.orderBy('rank', 'desc')
|
||||
.limit(searchParams.limit | 20)
|
||||
.offset(searchParams.offset || 0)
|
||||
.execute();
|
||||
|
||||
if (searchParams?.creatorId) {
|
||||
searchQueryBuilder.andWhere('page.creatorId = :creatorId', {
|
||||
creatorId: searchParams.creatorId,
|
||||
});
|
||||
}
|
||||
|
||||
searchQueryBuilder
|
||||
.take(searchParams.limit || 20)
|
||||
.offset(searchParams.offset || 0);
|
||||
|
||||
const results = await searchQueryBuilder.getRawMany();
|
||||
|
||||
const searchResults = results.map((result) => {
|
||||
const searchResults = queryResults.map((result) => {
|
||||
if (result.highlight) {
|
||||
result.highlight = result.highlight
|
||||
.replace(/\r\n|\r|\n/g, ' ')
|
||||
|
||||
Reference in New Issue
Block a user