[Search] Lunr search engine support (#5290)

* add lunr package

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* add search translator type and search engine interface

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* (wip) add support for lunr search engine

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* lunr search engine support

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* clean up todo comments

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* typing and cleanups

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* move lunr type package from dev deps to deps

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* check if documents exist to index

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* test fixup

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* changeset

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* move LunrSearchEngine.ts to /engines and add tests

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* update imports

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* update error message

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* add comment to index rotation

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* Update plugins/search-backend-node/src/types.ts

Signed-off-by: Fredrik Adelöw freben@gmail.com

Co-authored-by: Fredrik Adelöw <freben@gmail.com>
Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* Update plugins/search-backend-node/src/engines/LunrSearchEngine.ts

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

Co-authored-by: Fredrik Adelöw <freben@gmail.com>

* Update plugins/search-backend-node/src/engines/LunrSearchEngine.ts

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

Co-authored-by: Fredrik Adelöw <freben@gmail.com>

* fix imports

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* use type assertion to specify more specific ConcreteLunrQuery type

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* fix imports

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* consistent naming

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* change search engine to be parameter of constructor in indexBuilder

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* make engine required in router options and pass it through in createRouter used in standalone server

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* fix tests

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* delete import

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* add types to SearchQuery interface to make it possible to scope to specific index + test

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* clean up tests

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

* handle case when a filter is added on a field that does not exist on all documents + test

Signed-off-by: Emma Indal <emma.indahl@gmail.com>

Co-authored-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Emma Indal
2021-04-22 15:03:10 +02:00
committed by GitHub
parent 47d511b976
commit b9b2b4b766
16 changed files with 582 additions and 16 deletions
+1
View File
@@ -21,6 +21,7 @@
"dependencies": {
"@backstage/backend-common": "^0.6.0",
"@backstage/search-common": "^0.1.1",
"@backstage/plugin-search-backend-node": "^0.1.2",
"@types/express": "^4.17.6",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
@@ -15,6 +15,10 @@
*/
import { getVoidLogger } from '@backstage/backend-common';
import {
IndexBuilder,
LunrSearchEngine,
} from '@backstage/plugin-search-backend-node';
import express from 'express';
import request from 'supertest';
@@ -24,8 +28,12 @@ describe('createRouter', () => {
let app: express.Express;
beforeAll(async () => {
const logger = getVoidLogger();
const searchEngine = new LunrSearchEngine({ logger });
const indexBuilder = new IndexBuilder({ logger, searchEngine });
const router = await createRouter({
logger: getVoidLogger(),
engine: indexBuilder.getSearchEngine(),
logger,
});
app = express().use(router);
});
+8 -8
View File
@@ -18,23 +18,24 @@ import express from 'express';
import Router from 'express-promise-router';
import { Logger } from 'winston';
import { SearchQuery, SearchResultSet } from '@backstage/search-common';
import { SearchEngine } from '@backstage/plugin-search-backend-node';
type RouterOptions = {
engine: SearchEngine;
logger: Logger;
};
export async function createRouter({
engine,
logger,
}: RouterOptions): Promise<express.Router> {
const router = Router();
router.get(
'/query',
async (
req: express.Request<any, unknown, unknown, SearchQuery>,
res: express.Response<SearchResultSet>,
) => {
// TODO: Actually transform req.params into search engine specific query.
const { term, filters = {}, pageCursor = '' } = req.query;
logger.info(
`Search request received: ${term}, ${JSON.stringify(
@@ -43,13 +44,12 @@ export async function createRouter({
);
try {
// TODO: Actually query search engine.
// TODO: And actually transform results into frontend-readable result
res.send({
results: [],
});
const results = await engine?.query(req.query);
res.send(results);
} catch (err) {
throw new Error(`There was a problem performing the search query.`);
throw new Error(
`There was a problem performing the search query. ${err}`,
);
}
},
);
@@ -18,6 +18,10 @@ import { createServiceBuilder } from '@backstage/backend-common';
import { Server } from 'http';
import { Logger } from 'winston';
import { createRouter } from './router';
import {
LunrSearchEngine,
IndexBuilder,
} from '@backstage/plugin-search-backend-node';
export interface ServerOptions {
port: number;
@@ -29,8 +33,14 @@ export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'search-backend' });
const searchEngine = new LunrSearchEngine({ logger });
const indexBuilder = new IndexBuilder({ logger, searchEngine });
logger.debug('Starting application server...');
// TODO: stub out some documents/indices?
const router = await createRouter({
engine: indexBuilder.getSearchEngine(),
logger,
});