diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts index db92d79d71..51ab665026 100644 --- a/packages/backend/src/plugins/search.ts +++ b/packages/backend/src/plugins/search.ts @@ -39,7 +39,7 @@ async function createSearchEngine( } if (await PgSearchEngine.supported(env.database)) { - return await PgSearchEngine.from({ + return await PgSearchEngine.fromConfig({ database: env.database, config: env.config, }); diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts index c1ed730053..5ad9d12897 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.test.ts @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { ConfigReader } from '@backstage/config'; import { DatabaseStore } from '../database'; -import { PgSearchHighlightConfig } from '../types'; +import { PgSearchHighlightOptions } from '../types'; import { ConcretePgSearchQuery, decodePageCursor, @@ -23,7 +24,7 @@ import { } from './PgSearchEngine'; import { PgSearchEngineIndexer } from './PgSearchEngineIndexer'; -const highlightOptions: PgSearchHighlightConfig = { +const highlightOptions: PgSearchHighlightOptions = { preTag: '', postTag: '', useHighlight: true, @@ -47,6 +48,13 @@ describe('PgSearchEngine', () => { const tx: any = {} as any; let searchEngine: PgSearchEngine; let database: jest.Mocked; + const config = { + search: { + pg: { + highlightOptions, + }, + }, + }; beforeEach(() => { database = { @@ -57,7 +65,7 @@ describe('PgSearchEngine', () => { completeInsert: jest.fn(), prepareInsert: jest.fn(), }; - searchEngine = new PgSearchEngine(database); + searchEngine = new PgSearchEngine(database, new ConfigReader(config)); }); describe('translator', () => { diff --git a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts index d0c1571991..b6e57552ba 100644 --- a/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts +++ b/plugins/search-backend-module-pg/src/PgSearchEngine/PgSearchEngine.ts @@ -28,7 +28,7 @@ import { } from '../database'; import { v4 as uuid } from 'uuid'; import { Config } from '@backstage/config'; -import { PgSearchHighlightConfig, PgSearchHighlightOptions } from '../types'; +import { PgSearchHighlightOptions, PgSearchOptions } from '../types'; export type ConcretePgSearchQuery = { pgQuery: PgSearchQuery; @@ -36,36 +36,46 @@ export type ConcretePgSearchQuery = { }; export class PgSearchEngine implements SearchEngine { - private readonly highlightOptions: PgSearchHighlightConfig; - - constructor( - private readonly databaseStore: DatabaseStore, - highlightOptions?: PgSearchHighlightOptions, - ) { + private readonly highlightOptions: PgSearchHighlightOptions; + constructor(private readonly databaseStore: DatabaseStore, config: Config) { const uuidTag = uuid(); - this.highlightOptions = { + const highlightConfig = config.getOptionalConfig( + 'search.pg.highlightOptions', + ); + + const highlightOptions: PgSearchHighlightOptions = { preTag: `<${uuidTag}>`, postTag: ``, - useHighlight: true, - maxWords: 35, - minWords: 15, - shortWord: 3, - highlightAll: false, - maxFragments: 0, - fragmentDelimiter: ' ... ', - ...highlightOptions, + useHighlight: highlightConfig?.getOptionalBoolean('useHighlight') ?? true, + maxWords: highlightConfig?.getOptionalNumber('maxWords') ?? 35, + minWords: highlightConfig?.getOptionalNumber('minWords') ?? 15, + shortWord: highlightConfig?.getOptionalNumber('shortWord') ?? 3, + highlightAll: + highlightConfig?.getOptionalBoolean('highlightAll') ?? false, + maxFragments: highlightConfig?.getOptionalNumber('maxFragments') ?? 0, + fragmentDelimiter: + highlightConfig?.getOptionalString('fragmentDelimiter') ?? ' ... ', }; + this.highlightOptions = highlightOptions; } + /** + * @deprecated This will be removed in a future release, please us fromConfig instead + */ static async from(options: { database: PluginDatabaseManager; config: Config; }): Promise { return new PgSearchEngine( await DatabaseDocumentStore.create(await options.database.getClient()), - options.config.getOptional( - 'search.pg.highlightOptions', - ), + options.config, + ); + } + + static async fromConfig({ config, database }: PgSearchOptions) { + return new PgSearchEngine( + await DatabaseDocumentStore.create(await database.getClient()), + config, ); } @@ -75,7 +85,7 @@ export class PgSearchEngine implements SearchEngine { translator( query: SearchQuery, - options: PgSearchHighlightConfig, + options: PgSearchHighlightOptions, ): ConcretePgSearchQuery { const pageSize = 25; const { page } = decodePageCursor(query.pageCursor); diff --git a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts index 693a3ea3c0..f4b3e6fb0b 100644 --- a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts +++ b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.test.ts @@ -15,10 +15,10 @@ */ import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { IndexableDocument } from '@backstage/plugin-search-common'; -import { PgSearchHighlightConfig } from '../types'; +import { PgSearchHighlightOptions } from '../types'; import { DatabaseDocumentStore } from './DatabaseDocumentStore'; -const highlightOptions: PgSearchHighlightConfig = { +const highlightOptions: PgSearchHighlightOptions = { preTag: '', postTag: '', useHighlight: false, diff --git a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts index 1695db3cf5..040145f7b8 100644 --- a/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts +++ b/plugins/search-backend-module-pg/src/database/DatabaseDocumentStore.ts @@ -132,8 +132,9 @@ export class DatabaseDocumentStore implements DatabaseStore { async query( tx: Knex.Transaction, - { types, pgTerm, fields, offset, limit, options }: PgSearchQuery, + searchQuery: PgSearchQuery, ): Promise { + const { types, pgTerm, fields, offset, limit, options } = searchQuery; // Builds a query like: // SELECT ts_rank_cd(body, query) AS rank, type, document, // ts_headline('english', document, query) AS highlight diff --git a/plugins/search-backend-module-pg/src/database/types.ts b/plugins/search-backend-module-pg/src/database/types.ts index d572eba146..43bda32050 100644 --- a/plugins/search-backend-module-pg/src/database/types.ts +++ b/plugins/search-backend-module-pg/src/database/types.ts @@ -15,7 +15,7 @@ */ import { IndexableDocument } from '@backstage/plugin-search-common'; import { Knex } from 'knex'; -import { PgSearchHighlightConfig } from '../types'; +import { PgSearchHighlightOptions } from '../types'; export interface PgSearchQuery { fields?: Record; @@ -23,7 +23,7 @@ export interface PgSearchQuery { pgTerm?: string; offset: number; limit: number; - options: PgSearchHighlightConfig; + options: PgSearchHighlightOptions; } export interface DatabaseStore { diff --git a/plugins/search-backend-module-pg/src/index.ts b/plugins/search-backend-module-pg/src/index.ts index fbc52735dd..4cb54f9676 100644 --- a/plugins/search-backend-module-pg/src/index.ts +++ b/plugins/search-backend-module-pg/src/index.ts @@ -22,3 +22,4 @@ export * from './database'; export * from './PgSearchEngine'; +export type { PgSearchHighlightOptions } from './types'; diff --git a/plugins/search-backend-module-pg/src/types.ts b/plugins/search-backend-module-pg/src/types.ts index 9ad56b9b12..5e32c69e7a 100644 --- a/plugins/search-backend-module-pg/src/types.ts +++ b/plugins/search-backend-module-pg/src/types.ts @@ -14,6 +14,22 @@ * limitations under the License. */ +import { PluginDatabaseManager } from '@backstage/backend-common'; +import { Config } from '@backstage/config'; + +/** + * Options to instantiate PgSearchEngine + * @public + */ +export type PgSearchOptions = { + config: Config; + database: PluginDatabaseManager; +}; + +/** + * Options for highlighting search terms + * @public + */ export type PgSearchHighlightOptions = { useHighlight?: boolean; maxWords?: number; @@ -22,19 +38,6 @@ export type PgSearchHighlightOptions = { highlightAll?: boolean; maxFragments?: number; fragmentDelimiter?: string; -}; - -/** - * @public - */ -export type PgSearchHighlightConfig = { - useHighlight: boolean; - maxWords: number; - minWords: number; - shortWord: number; - highlightAll: boolean; - maxFragments: number; - fragmentDelimiter: string; preTag: string; postTag: string; };