Skip to content

Commit

Permalink
fix: reduce search index size
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanHotsiy committed May 18, 2018
1 parent 8afae47 commit a1fa4b4
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 37 deletions.
19 changes: 7 additions & 12 deletions src/components/SearchBox/SearchBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { SearchStore } from '../../services/SearchStore';
import { MenuItem } from '../SideMenu/MenuItem';

import { MarkerService } from '../../services/MarkerService';
import { SearchDocument } from '../../services/SearchWorker.worker';
import { SearchResult } from '../../services/SearchWorker.worker';

import {
ClearIcon,
Expand All @@ -16,7 +16,7 @@ import {
} from './styled.elements';

export interface SearchBoxProps {
search: SearchStore;
search: SearchStore<string>;
marker: MarkerService;
getItemById: (id: string) => IMenuItem | undefined;
onActivate: (item: IMenuItem) => void;
Expand All @@ -25,16 +25,11 @@ export interface SearchBoxProps {
}

export interface SearchBoxState {
results: any;
results: SearchResult[];
term: string;
activeItemIdx: number;
}

interface SearchResult {
item: IMenuItem;
score: number;
}

export class SearchBox extends React.PureComponent<SearchBoxProps, SearchBoxState> {
activeItemRef: MenuItem | null = null;

Expand Down Expand Up @@ -87,15 +82,15 @@ export class SearchBox extends React.PureComponent<SearchBoxProps, SearchBoxStat
// enter
const activeResult = this.state.results[this.state.activeItemIdx];
if (activeResult) {
const item = this.props.getItemById(activeResult.id);
const item = this.props.getItemById(activeResult.meta);
if (item) {
this.props.onActivate(item);
}
}
}
};

setResults(results: SearchDocument[], term: string) {
setResults(results: SearchResult[], term: string) {
this.setState({
results,
term,
Expand All @@ -121,8 +116,8 @@ export class SearchBox extends React.PureComponent<SearchBoxProps, SearchBoxStat

render() {
const { activeItemIdx } = this.state;
const results: SearchResult[] = this.state.results.map(res => ({
item: this.props.getItemById(res.id),
const results = this.state.results.map(res => ({
item: this.props.getItemById(res.meta)!,
score: res.score,
}));

Expand Down
2 changes: 1 addition & 1 deletion src/services/AppStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class AppStore {
spec: SpecStore;
rawOptions: RedocRawOptions;
options: RedocNormalizedOptions;
search: SearchStore;
search: SearchStore<string>;
marker = new MarkerService();

private scroll: ScrollService;
Expand Down
8 changes: 4 additions & 4 deletions src/services/SearchStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if (IS_BROWSER) {
worker = require('./SearchWorker.worker').default;
}

export class SearchStore {
export class SearchStore<T> {
searchWorker = new worker();

indexItems(groups: Array<IMenuItem | OperationModel>) {
Expand All @@ -34,12 +34,12 @@ export class SearchStore {
this.searchWorker.done();
}

add(title: string, body: string, ref: string) {
this.searchWorker.add(title, body, ref);
add(title: string, body: string, meta?: T) {
this.searchWorker.add(title, body, meta);
}

search(q: string) {
return this.searchWorker.search(q);
return this.searchWorker.search<T>(q);
}

async toJS() {
Expand Down
51 changes: 31 additions & 20 deletions src/services/SearchWorker.worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import * as lunr from 'lunr';

/* just for better typings */
export default class Worker {
add = add;
add: typeof add = add;
done = done;
search = search;
search: typeof search = search;
toJS = toJS;
load = load;
}
Expand All @@ -15,11 +15,12 @@ export interface SearchDocument {
id: string;
}

export interface SearchResult extends SearchDocument {
export interface SearchResult<T = string> {
meta: T;
score: number;
}

let store: { [id: string]: SearchDocument } = {};
let store: any[] = [];

let resolveIndex: (v: lunr.Index) => void = () => {
throw new Error('Should not be called');
Expand All @@ -29,19 +30,21 @@ const index: Promise<lunr.Index> = new Promise(resolve => {
resolveIndex = resolve;
});

lunr.tokenizer.separator = /\s+/;

const builder = new lunr.Builder();
builder.field('title');
builder.field('description');
builder.ref('id');
builder.ref('ref');

builder.pipeline.add(lunr.trimmer, lunr.stopWordFilter, lunr.stemmer);

const expandTerm = term => '*' + lunr.stemmer(new lunr.Token(term, {})) + '*';

export function add(title: string, description: string, id: string) {
const item = { title, description, id };
export function add<T>(title: string, description: string, meta?: T) {
const ref = store.push(meta) - 1;
const item = { title: title.toLowerCase(), description: description.toLowerCase(), ref };
builder.add(item);
store[id] = item;
}

export async function done() {
Expand All @@ -60,20 +63,28 @@ export async function load(state: any) {
resolveIndex(lunr.Index.load(state.index));
}

export async function search(q: string): Promise<Array<SearchDocument & SearchResult>> {
export async function search<Meta = string>(
q: string,
limit = 0,
): Promise<Array<SearchResult<Meta>>> {
if (q.trim().length === 0) {
return [];
}

return (await index)
.query(t => {
q
.trim()
.split(/\s+/)
.forEach(term => {
const exp = expandTerm(term);
t.term(exp, {});
});
})
.map(res => ({ ...store[res.ref], score: res.score }));
let searchResults = (await index).query(t => {
q
.trim()
.toLowerCase()
.split(/\s+/)
.forEach(term => {
const exp = expandTerm(term);
t.term(exp, {});
});
});

if (limit > 0) {
searchResults = searchResults.slice(0, limit);
}

return searchResults.map(res => ({ meta: store[res.ref], score: res.score }));
}

0 comments on commit a1fa4b4

Please sign in to comment.