refactor(core): new quick search service (#7214)

This commit is contained in:
EYHN
2024-07-02 09:17:53 +00:00
parent 15e99c7819
commit 40e381e272
63 changed files with 1809 additions and 2007 deletions

View File

@@ -1,14 +1,16 @@
import {
fromPromise,
OnEvent,
Service,
WorkspaceEngineBeforeStart,
} from '@toeverything/infra';
import { type Observable, switchMap } from 'rxjs';
import { DocsIndexer } from '../entities/docs-indexer';
@OnEvent(WorkspaceEngineBeforeStart, s => s.handleWorkspaceEngineBeforeStart)
export class DocsSearchService extends Service {
private readonly indexer = this.framework.createEntity(DocsIndexer);
readonly indexer = this.framework.createEntity(DocsIndexer);
handleWorkspaceEngineBeforeStart() {
this.indexer.setupListener();
@@ -115,6 +117,114 @@ export class DocsSearchService extends Service {
return result;
}
search$(query: string): Observable<
{
docId: string;
title: string;
score: number;
blockId?: string;
blockContent?: string;
}[]
> {
return this.indexer.blockIndex
.aggregate$(
{
type: 'boolean',
occur: 'must',
queries: [
{
type: 'match',
field: 'content',
match: query,
},
{
type: 'boolean',
occur: 'should',
queries: [
{
type: 'all',
},
{
type: 'boost',
boost: 100,
query: {
type: 'match',
field: 'flavour',
match: 'affine:page',
},
},
],
},
],
},
'docId',
{
pagination: {
limit: 50,
skip: 0,
},
hits: {
pagination: {
limit: 2,
skip: 0,
},
fields: ['blockId', 'flavour'],
highlights: [
{
field: 'content',
before: '<b>',
end: '</b>',
},
],
},
}
)
.pipe(
switchMap(({ buckets }) => {
return fromPromise(async () => {
const docData = await this.indexer.docIndex.getAll(
buckets.map(bucket => bucket.key)
);
const result = [];
for (const bucket of buckets) {
const firstMatchFlavour = bucket.hits.nodes[0]?.fields.flavour;
if (firstMatchFlavour === 'affine:page') {
// is title match
const blockContent =
bucket.hits.nodes[1]?.highlights.content[0]; // try to get block content
result.push({
docId: bucket.key,
title: bucket.hits.nodes[0].highlights.content[0],
score: bucket.score,
blockContent,
});
} else {
const title =
docData.find(doc => doc.id === bucket.key)?.get('title') ??
'';
const matchedBlockId = bucket.hits.nodes[0]?.fields.blockId;
// is block match
result.push({
docId: bucket.key,
title: typeof title === 'string' ? title : title[0],
blockId:
typeof matchedBlockId === 'string'
? matchedBlockId
: matchedBlockId[0],
score: bucket.score,
blockContent: bucket.hits.nodes[0]?.highlights.content[0],
});
}
}
return result;
});
})
);
}
async getDocTitle(docId: string) {
const doc = await this.indexer.docIndex.get(docId);
const title = doc?.get('title');