From 79b4390911dfe0d6114c00c62510ea5e6c9497c7 Mon Sep 17 00:00:00 2001 From: Vyacheslav Tumanov <me@slavatumanov.me> Date: Sun, 10 Mar 2024 20:45:56 +0500 Subject: [PATCH] 5 results per class in search (#4914) Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me> --- packages/core/src/storage.ts | 1 + packages/presentation/src/search.ts | 36 +++++++++++++++++++---------- server/core/src/mapper.ts | 3 ++- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/packages/core/src/storage.ts b/packages/core/src/storage.ts index 98cfdab27d..df77cc2cbb 100644 --- a/packages/core/src/storage.ts +++ b/packages/core/src/storage.ts @@ -230,6 +230,7 @@ export interface SearchResultDoc { iconProps?: Record<string, string> shortTitle?: string title?: string + score?: number doc: Pick<Doc, '_id' | '_class'> } diff --git a/packages/presentation/src/search.ts b/packages/presentation/src/search.ts index 269f0a5847..fe62e690ee 100644 --- a/packages/presentation/src/search.ts +++ b/packages/presentation/src/search.ts @@ -13,7 +13,7 @@ // limitations under the License. // -import type { Class, Ref, Doc, SearchResultDoc, TxOperations } from '@hcengineering/core' +import type { Class, Ref, Doc, SearchResultDoc, TxOperations, SearchResult } from '@hcengineering/core' import { type ObjectSearchCategory } from './types' import plugin from './plugin' import { getClient } from './utils' @@ -67,18 +67,27 @@ async function doFulltextSearch ( query: string, categories: ObjectSearchCategory[] ): Promise<SearchSection[]> { - const result = await client.searchFulltext( - { - query: `${query}*`, - classes - }, - { - limit: 10 + let result: SearchResult | undefined + for (const cl of classes) { + const r = await client.searchFulltext( + { + query: `${query}*`, + classes: [cl] + }, + { + limit: 5 + } + ) + if (result === undefined) { + result = r + } else { + result.docs.push(...r.docs) + result.total = (result?.total ?? 0) + (r.total ?? 0) } - ) + } const itemsByClass = new Map<Ref<Class<Doc>>, SearchResultDoc[]>() - for (const item of result.docs) { + for (const item of result?.docs ?? []) { const list = itemsByClass.get(item.doc._class) if (list === undefined) { itemsByClass.set(item.doc._class, [item]) @@ -94,8 +103,11 @@ async function doFulltextSearch ( sections.push({ category, items }) } } - - return sections + return sections.sort((a, b) => { + const maxScoreA = Math.max(...(a?.items ?? []).map((obj) => obj?.score ?? 0)) + const maxScoreB = Math.max(...(b?.items ?? []).map((obj) => obj?.score ?? 0)) + return maxScoreB - maxScoreA + }) } const categoriesByContext = new Map<string, ObjectSearchCategory[]>() diff --git a/server/core/src/mapper.ts b/server/core/src/mapper.ts index 9f26cd7fd8..7b38122816 100644 --- a/server/core/src/mapper.ts +++ b/server/core/src/mapper.ts @@ -172,7 +172,8 @@ export function mapSearchResultDoc (hierarchy: Hierarchy, raw: IndexedDoc): Sear doc: { _id: raw.id, _class: raw._class - } + }, + score: raw._score } const searchPresenter = findSearchPresenter(hierarchy, doc.doc._class)