diff --git a/packages/@ourworldindata/grapher/src/controls/entityPicker/EntityPicker.tsx b/packages/@ourworldindata/grapher/src/controls/entityPicker/EntityPicker.tsx index 0cdcd7d801..4ef0eb9781 100644 --- a/packages/@ourworldindata/grapher/src/controls/entityPicker/EntityPicker.tsx +++ b/packages/@ourworldindata/grapher/src/controls/entityPicker/EntityPicker.tsx @@ -258,9 +258,9 @@ export class EntityPicker extends React.Component<{ } @computed private get fuzzy(): FuzzySearch { - return new FuzzySearch( + return FuzzySearch.withKey( this.entitiesWithMetricValue, - OwidTableSlugs.entityName + (entity) => entity.entityName ) } diff --git a/packages/@ourworldindata/grapher/src/entitySelector/EntitySelector.tsx b/packages/@ourworldindata/grapher/src/entitySelector/EntitySelector.tsx index c4ee1c8c30..4ab3dc5be5 100644 --- a/packages/@ourworldindata/grapher/src/entitySelector/EntitySelector.tsx +++ b/packages/@ourworldindata/grapher/src/entitySelector/EntitySelector.tsx @@ -548,7 +548,10 @@ export class EntitySelector extends React.Component<{ } @computed get fuzzy(): FuzzySearch { - return new FuzzySearch(this.sortedAvailableEntities, "name") + return FuzzySearch.withKey( + this.sortedAvailableEntities, + (entity) => entity.name + ) } @computed get searchResults(): SearchableEntity[] | undefined { diff --git a/packages/@ourworldindata/utils/src/FuzzySearch.ts b/packages/@ourworldindata/utils/src/FuzzySearch.ts index 374ae73ef4..faa3f91def 100644 --- a/packages/@ourworldindata/utils/src/FuzzySearch.ts +++ b/packages/@ourworldindata/utils/src/FuzzySearch.ts @@ -6,12 +6,47 @@ export class FuzzySearch { datamap: Record opts: Fuzzysort.Options | undefined - constructor(data: T[], key: keyof T, opts?: Fuzzysort.Options) { - this.datamap = groupBy(data, key) - this.strings = data.map((d) => fuzzysort.prepare(d[key] as string)) + private constructor( + datamap: Record, + opts?: Fuzzysort.Options + ) { + const rawStrings = Object.keys(datamap) + this.strings = rawStrings.map((s) => fuzzysort.prepare(s)) + this.datamap = datamap this.opts = opts } + static withKey( + data: T[], + key: (obj: T) => string, + opts?: Fuzzysort.Options + ): FuzzySearch { + const datamap = groupBy(data, key) + return new FuzzySearch(datamap, opts) + } + + // Allows for multiple keys per object, e.g. aliases: + // [ + // { name: "Netherlands", "keys": ["Netherlands", "Nederland"] }, + // { name: "Spain", "keys": ["Spain", "EspaƱa"] }, + // ] + // Note that the calling site will need to take care of uniqueness of results, + // if that's desired, e.g. using uniqBy(results, "name") + static withKeyArray( + data: T[], + keys: (obj: T) => string[], + opts?: Fuzzysort.Options + ): FuzzySearch { + const datamap: Record = {} + data.forEach((d) => { + keys(d).forEach((key) => { + if (!datamap[key]) datamap[key] = [d] + else datamap[key].push(d) + }) + }) + return new FuzzySearch(datamap, opts) + } + search(input: string): T[] { return fuzzysort .go(input, this.strings, this.opts) diff --git a/site/runCountryProfilePage.ts b/site/runCountryProfilePage.ts index 62480452cb..f964c36a07 100644 --- a/site/runCountryProfilePage.ts +++ b/site/runCountryProfilePage.ts @@ -25,7 +25,9 @@ class ChartFilter { @observable query: string = "" @computed private get fuzzy(): FuzzySearch { - return new FuzzySearch(this.chartItems, "title", { threshold: -150 }) + return FuzzySearch.withKey(this.chartItems, (chart) => chart.title, { + threshold: -150, + }) } @computed get searchResults() {