mirror of
https://github.com/PeWu/topola-viewer.git
synced 2026-03-13 19:13:43 +00:00
Index husband's last name for better search results
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import naturalSort from 'javascript-natural-sort';
|
import naturalSort from 'javascript-natural-sort';
|
||||||
import lunr from 'lunr';
|
import lunr from 'lunr';
|
||||||
import {GedcomData} from './gedcom_util';
|
import {GedcomData, pointerToId} from './gedcom_util';
|
||||||
import {GedcomEntry} from 'parse-gedcom';
|
import {GedcomEntry} from 'parse-gedcom';
|
||||||
|
|
||||||
const MAX_RESULTS = 8;
|
const MAX_RESULTS = 8;
|
||||||
@@ -26,27 +26,67 @@ function normalize(input: string) {
|
|||||||
/** Comparator to sort by score first, then by id. */
|
/** Comparator to sort by score first, then by id. */
|
||||||
function compare(a: lunr.Index.Result, b: lunr.Index.Result) {
|
function compare(a: lunr.Index.Result, b: lunr.Index.Result) {
|
||||||
if (a.score !== b.score) {
|
if (a.score !== b.score) {
|
||||||
return a.score - b.score;
|
return b.score - a.score;
|
||||||
}
|
}
|
||||||
return naturalSort(a.ref, b.ref);
|
return naturalSort(a.ref, b.ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LunrSearchIndex implements SearchIndex {
|
/** Returns all last names of all husbands as a space-separated string. */
|
||||||
private index: lunr.Index;
|
function getHusbandLastName(indi: GedcomEntry, gedcom: GedcomData): string {
|
||||||
|
return indi.tree
|
||||||
|
.filter((entry) => entry.tag === 'FAMS')
|
||||||
|
.map((entry) => gedcom.fams[pointerToId(entry.data)])
|
||||||
|
.filter((entry) => !!entry)
|
||||||
|
.map((entry) => {
|
||||||
|
const husband = entry.tree.find((entry) => entry.tag === 'HUSB');
|
||||||
|
const husbandId = husband && pointerToId(husband.data);
|
||||||
|
return (
|
||||||
|
husbandId &&
|
||||||
|
husbandId !== pointerToId(indi.pointer) &&
|
||||||
|
gedcom.indis[husbandId]
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.filter((entry) => !!entry)
|
||||||
|
.flatMap((husband) =>
|
||||||
|
(husband as GedcomEntry).tree
|
||||||
|
.filter((entry) => entry.tag === 'NAME')
|
||||||
|
.map((entry) => {
|
||||||
|
const names = entry.data.split('/');
|
||||||
|
return names.length >= 2 ? names[1] : '';
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
public constructor(private gedcom: GedcomData) {
|
class LunrSearchIndex implements SearchIndex {
|
||||||
|
private index: lunr.Index | undefined;
|
||||||
|
|
||||||
|
constructor(private gedcom: GedcomData) {}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
const self = this;
|
||||||
this.index = lunr(function() {
|
this.index = lunr(function() {
|
||||||
this.ref('id');
|
this.ref('id');
|
||||||
this.field('id');
|
this.field('id');
|
||||||
this.field('name');
|
this.field('name', {boost: 10});
|
||||||
this.field('normalizedName');
|
this.field('normalizedName', {boost: 8});
|
||||||
|
this.field('spouseLastName', {boost: 2});
|
||||||
|
this.field('normalizedSpouseLastName', {boost: 2});
|
||||||
|
|
||||||
for (let id in gedcom.indis) {
|
for (let id in self.gedcom.indis) {
|
||||||
const name = gedcom.indis[id].tree
|
const indi = self.gedcom.indis[id];
|
||||||
|
const name = indi.tree
|
||||||
.filter((entry) => entry.tag === 'NAME')
|
.filter((entry) => entry.tag === 'NAME')
|
||||||
.map((entry) => entry.data)
|
.map((entry) => entry.data)
|
||||||
.join(' ');
|
.join(' ');
|
||||||
this.add({id, name, normalizedName: normalize(name)});
|
const spouseLastName = getHusbandLastName(indi, self.gedcom);
|
||||||
|
this.add({
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
normalizedName: normalize(name),
|
||||||
|
spouseLastName,
|
||||||
|
normalizedSpouseLastName: normalize(spouseLastName),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -57,7 +97,7 @@ class LunrSearchIndex implements SearchIndex {
|
|||||||
.filter((s) => !!s)
|
.filter((s) => !!s)
|
||||||
.map((s) => `+${s}*`)
|
.map((s) => `+${s}*`)
|
||||||
.join(' ');
|
.join(' ');
|
||||||
const results = this.index.search(query);
|
const results = this.index!.search(query);
|
||||||
return results
|
return results
|
||||||
.sort(compare)
|
.sort(compare)
|
||||||
.slice(0, MAX_RESULTS)
|
.slice(0, MAX_RESULTS)
|
||||||
@@ -67,5 +107,7 @@ class LunrSearchIndex implements SearchIndex {
|
|||||||
|
|
||||||
/** Builds a search index from data. */
|
/** Builds a search index from data. */
|
||||||
export function buildSearchIndex(gedcom: GedcomData): SearchIndex {
|
export function buildSearchIndex(gedcom: GedcomData): SearchIndex {
|
||||||
return new LunrSearchIndex(gedcom);
|
const index = new LunrSearchIndex(gedcom);
|
||||||
|
index.initialize();
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|||||||
import debounce from 'debounce';
|
import debounce from 'debounce';
|
||||||
import md5 from 'md5';
|
import md5 from 'md5';
|
||||||
import {analyticsEvent} from './analytics';
|
import {analyticsEvent} from './analytics';
|
||||||
import {buildSearchIndex, SearchIndex, SearchResult} from './search_index';
|
import {buildSearchIndex, SearchIndex} from './search_index';
|
||||||
import {displaySearchResult} from './search_util';
|
import {displaySearchResult} from './search_util';
|
||||||
import {FormattedMessage, intlShape} from 'react-intl';
|
import {FormattedMessage, intlShape} from 'react-intl';
|
||||||
import {GedcomData} from './gedcom_util';
|
import {GedcomData} from './gedcom_util';
|
||||||
@@ -21,13 +21,14 @@ import {
|
|||||||
Dropdown,
|
Dropdown,
|
||||||
Search,
|
Search,
|
||||||
SearchProps,
|
SearchProps,
|
||||||
|
SearchResultProps,
|
||||||
} from 'semantic-ui-react';
|
} from 'semantic-ui-react';
|
||||||
|
|
||||||
/** Menus and dialogs state. */
|
/** Menus and dialogs state. */
|
||||||
interface State {
|
interface State {
|
||||||
loadUrlDialogOpen: boolean;
|
loadUrlDialogOpen: boolean;
|
||||||
url?: string;
|
url?: string;
|
||||||
searchResults: SearchResult[];
|
searchResults: SearchResultProps[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EventHandlers {
|
interface EventHandlers {
|
||||||
|
|||||||
Reference in New Issue
Block a user