From e7638fa7e7df44fa33fbc615fd8ab85656191756 Mon Sep 17 00:00:00 2001 From: Emma Indal Date: Thu, 30 Jun 2022 16:03:52 +0200 Subject: [PATCH] delete beta related how to guides Signed-off-by: Emma Indal --- docs/features/search/how-to-guides.md | 265 -------------------------- 1 file changed, 265 deletions(-) diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md index fb0883d506..01d85b8aa2 100644 --- a/docs/features/search/how-to-guides.md +++ b/docs/features/search/how-to-guides.md @@ -148,271 +148,6 @@ indexBuilder.addCollator({ As shown above, you can add a catalog entity filter to narrow down what catalog entities are indexed by the search engine. -## How to migrate from Search Alpha to Beta - -For the purposes of this guide, Search Beta version is defined as: - -- **Search Plugin**: At least `v0.7.2` -- **Search Backend Plugin**: At least `v0.4.6` -- **Search Backend Node**: At least `v0.5.0` -- **Search Common**: At least `v0.3.0` - -In the Beta version, the Search Platform's indexing process has been rewritten -as a stream pipeline in order to improve efficiency and performance on large -sets of documents. - -If you've not yet extended the Search Platform with custom code, and have -instead taken advantage of default collators, decorators, and search engines -provided by existing plugins, the migration process is fairly straightforward: - -1. Upgrade to at least version `0.5.0` of - `@backstage/plugin-search-backend-node`, as well as any backend plugins whose - collators you are using (e.g. at least version `0.23.0` of - `@backstage/plugin-catalog-backend` and/or version `0.14.1` of - `@backstage/plugin-techdocs-backend`), as well as any search-engine specific - plugin you are using (e.g. at least version `0.3.0` of - `@backstage/plugin-search-backend-module-pg` or version `0.1.0` of - `@backstage/plugin-search-backend-module-elasticsearch`). -2. Then, make the following changes to your - `/packages/backend/src/plugins/search.ts` file: - - ```diff - -import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend'; - -import { DefaultTechDocsCollator } from '@backstage/plugin-techdocs-backend'; - +import { DefaultCatalogCollatorFactory } from '@backstage/plugin-catalog-backend'; - +import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend'; - // ... - const indexBuilder = new IndexBuilder({ logger: env.logger, searchEngine }); - indexBuilder.addCollator({ - defaultRefreshIntervalSeconds: 600, - - collator: DefaultCatalogCollator.fromConfig(env.config, { - discovery: env.discovery, - }), - + factory: DefaultCatalogCollatorFactory.fromConfig(env.config, { - discovery: env.discovery, - }), - }); - indexBuilder.addCollator({ - defaultRefreshIntervalSeconds: 600, - - collator: DefaultTechDocsCollator.fromConfig(env.config, { - + factory: DefaultTechDocsCollatorFactory.fromConfig(env.config, { - discovery: env.discovery, - logger: env.logger, - }), - }); - ``` - -Any custom collators, decorators, or search engine implementations will require -minor refactoring. Continue on for details. - -### Rewriting alpha-style collators for beta - -In alpha versions of the Backstage Search Platform, collators were classes that -implemented an `execute` method which resolved an `IndexableDocument` array. - -In beta versions, the logic encapsulated by the aforementioned `execute` method -is contained within an [object-mode][obj-mode] `Readable` stream where each -object pushed onto the stream is of type `IndexableDocument`. Instances of this -stream are instantiated by a factory class conforming to the -`DocumentCollatorFactory` interface. - -The optimal conversion strategy will vary depending on the collator's logic, but -the simplest conversion can follow a process like this: - -1. Rename your collator class to something like `YourCollatorFactory` and update - it to implement `DocumentCollatorFactory` instead of `DocumentCollator`. -2. Update its `execute` method so that it resolves - `AsyncGenerator` instead of `YourIndexableDocument[]`. -3. Implement `DocumentCollatorFactory`'s `getCollator` method which resolves to - `Readable.from(this.execute())` (which is a utility for creating [readable - streams][read-stream] from [async generators][async-gen]). - -```ts -import { DocumentCollatorFactory } from '@backstage/plugin-search-backend-node'; -import { Readable } from 'stream'; -export class YourCollatorFactory implements DocumentCollatorFactory { - public readonly type: string = 'your-type'; - async *execute(): AsyncGenerator { - const widgets = await this.client.getWidgets(); - for (const widget of widgets) { - yield { - title: widget.name, - location: widget.url, - text: widget.description, - }; - } - } - async getCollator() { - return Readable.from(this.execute()); - } -} -``` - -Note: it may be possible to simplify your collator dramatically! If your custom -collator was previously using streams under the hood (for example, by reading -newline delimited JSON from a local or remote file), you could just expose the -stream directly via a simple factory class: - -```ts -import { DocumentCollatorFactory } from '@backstage/plugin-search-backend-node'; -import { createReadStream } from 'fs'; -import { parse } from '@jsonlines/core'; -export class YourCollatorFactory implements DocumentCollatorFactory { - public readonly type: string = 'your-type'; - async getCollator() { - const parseStream = parse(); - return createReadStream('./documents.ndjson').pipe(parseStream); - } -} -``` - -### Rewriting alpha-style decorators for beta - -In alpha versions of the Backstage Search Platform, decorators were classes that -implemented an `execute` method which took an `IndexableDocument` array as an -argument, and resolved a modified array of the same type. - -In beta versions, the logic encapsulated by the aforementioned `execute` method -is contained within an object-mode `Transform` stream which reads objects of -type `IndexableDocument`, and writes objects of a conforming type. Similar to -collators, instances of this stream are instantiated by a factory class -conforming to the `DocumentDecoratorFactory` interface. - -Although you can choose to implement a `Transform` stream from scratch, the -`@backstage/plugin-search-backend-node` package provides a `DecoratorBase` class -in order to simplify the developer experience. With this base class, all that's -needed is to transfer your old decorator class logic into the base class' three -methods (`initialize`, `decorate`, and `finalize`), and implement the factory -class that instantiates the stream: - -```ts -import { DecoratorBase } from '@backstage/plugin-search-backend-node'; -export class YourDecorator extends DecoratorBase { - async initialize() { - // Setup logic. Performed once before any documents are consumed. - } - async decorate( - document: YourIndexableDocument, - ): Promise { - // Perform transformation logic here. - return document; - } - async finalize() { - // Teardown logic. Performed once after all documents have been consumed. - } -} -export class YourDecoratorFactory implements DocumentDecoratorFactory { - async getDecorator() { - return new YourDecorator(); - } -} -``` - -Note the return type of the `decorate` method and how each can be used to -different effect. - -- By resolving a single `YourIndexableDocument` object, your decorator can be - used to make simple transformations: - - ```ts - class BooleanWidgetCoolnessDecorator extends DecoratorBase { - async decorator(widget) { - // Perform a simple, 1:1 transformation. - widget.isCool = widget.isCool === 'true' ? true : false; - return widget; - } - } - ``` - -- By resolving `undefined`, your decorator can filter out documents which - shouldn't be in the index: - - ```ts - class OnlyCoolWidgetsDecorator extends DecoratorBase { - async decorator(widget) { - // Perform a simple filter operation. - return widget.isCool ? widget : undefined; - } - } - ``` - -- By resolving an array of `YourIndexableDocument` objects, you can generate - multiple documents based on the content of one: - - ```ts - class WidgetByVariantDecorator extends DecoratorBase { - async decorator(widget) { - // Generate one widget doc per widget variant. - return widget.variants.map(variant => { - // Each widget doc is the given widget plus a "variant" property - // pulled from a widget.variants string array. - return { - ...widget, - variant, - }; - }); - } - } - ``` - -In alpha versions, a decorator had access to every `IndexableDocument` -simultaneously. This is no longer possible in beta versions (precisely to make -the indexing process more efficient and performant). You will need to modify -your decorator's logic so that it does not need access to every document at -once. - -### Rewriting alpha-style search engines for beta - -Search Engines are responsible for both querying and indexing documents to an -underlying search engine technology. While the search engine query interface -didn't change between alpha and beta versions, the indexing half of the -interface _did_ change. - -In alpha versions of the Backstage Search Platform, a search engine implemented -an `index` method which took a `type` and an `IndexableDocument` array and was -responsible for writing these documents to the underlying search engine. - -In beta versions, the logic encapsulated by the aforementioned `index` method is -contained within an object-mode `Writable` stream which expects objects of type -`IndexableDocument`. On the search engine class itself, the `index` method is -replaced with a `getIndexer` factory method which still takes the `type`, but -resolves an instance of the aforementioned `Writable` stream. - -Although you can choose to implement a `Writable` stream from scratch, the -`@backstage/plugin-search-backend-node` package provides a -`BatchSearchEngineIndexer` class in order to simplify the developer experience. -With this base class, which collects documents in batches of a configurable size -on your behalf, all that's needed is to transfer your old `index` method logic -into the base class' three methods (`initialize`, `index`, and `finalize`), and -implement the factory method that instantiates the stream: - -```ts -import { BatchSearchEngineIndexer } from '@backstage/plugin-search-backend-node'; -import { SearchEngine } from '@backstage/plugin-search-common'; -export class YourSearchEngineIndexer extends BatchSearchEngineIndexer { - constructor({ type }: { type: string }) { - // Customize the number of documents passed to the index method per batch. - super({ batchSize: 500 }); - // An imaginary search engine indexing client. - this.index = new SomeSearchEngineIndex({ indexName: type }); - } - async initialize() { - // Setup logic. Performed once before any documents are consumed. - } - async index(documents: IndexableDocument[]) { - await this.index.batchOf(documents); - } - async finalize() { - // Teardown logic. Performed once after all documents have been consumed. - } -} -export class YourSearchEngine implements SearchEngine { - async getIndexer(type: string) { - return new YourSearchEngineIndexer({ type }); - } -} -``` - ## How to customize search results highlighting styling The default highlighting styling for matched terms in search results is your