Further refactoring of algolia indexing

This commit is contained in:
Piotr Janosz
2019-07-29 15:28:26 +02:00
committed by fabioberger
parent f1f38fb8b0
commit 9b9ee2415d
9 changed files with 57 additions and 34 deletions

View File

@@ -7,7 +7,7 @@ const filter = require('unist-util-filter');
const { selectAll } = require('unist-util-select'); const { selectAll } = require('unist-util-select');
const extractMdxMeta = require('extract-mdx-metadata'); const extractMdxMeta = require('extract-mdx-metadata');
function processContentTree(tree: Node[], url: string, meta: Meta, index: any): void { function processContentTree(tree: Node[], url: string, meta: Meta, index: any, settings: Settings): void {
const filteredTree = filter(tree, () => { const filteredTree = filter(tree, () => {
return (node: Node) => node.type === 'heading' || node.type === 'paragraph'; return (node: Node) => node.type === 'heading' || node.type === 'paragraph';
}); });
@@ -18,11 +18,12 @@ function processContentTree(tree: Node[], url: string, meta: Meta, index: any):
const formattedTextNodes = formatTextNodes(textNodes); const formattedTextNodes = formatTextNodes(textNodes);
const content = getContent(meta, url, formattedTextNodes); const content = getContent(meta, url, formattedTextNodes);
setIndexSettings(index, settings);
pushObjectsToAlgolia(index, content); pushObjectsToAlgolia(index, content);
} }
} }
export function setIndexSettings(index: any, settings: Settings): void { function setIndexSettings(index: any, settings: Settings): void {
index.setSettings(settings, (err: string) => { index.setSettings(settings, (err: string) => {
if (err) { if (err) {
throw Error(`Error: ${err}`); throw Error(`Error: ${err}`);
@@ -80,7 +81,7 @@ function formatTextNodes(textNodes: Node[]): FormattedNode[] {
return formattedTextNodes; return formattedTextNodes;
} }
async function processMdxAsync(index: any, dirName: string, fileName: string): Promise<void> { async function processMdxAsync(index: any, dirName: string, fileName: string, settings: Settings): Promise<void> {
const filePath = `${dirName}/${fileName}`; const filePath = `${dirName}/${fileName}`;
const { name } = path.parse(filePath); // Name without file extension const { name } = path.parse(filePath); // Name without file extension
const url = `/docs/${dirName}/${name}`; const url = `/docs/${dirName}/${name}`;
@@ -91,14 +92,14 @@ async function processMdxAsync(index: any, dirName: string, fileName: string): P
await remark() await remark()
.use(mdx) .use(mdx)
.use(() => (tree: Node[]) => processContentTree(tree, url, meta, index)) .use(() => (tree: Node[]) => processContentTree(tree, url, meta, index, settings))
.process(file); .process(file);
} }
export async function indexFilesAsync(index: any, dirName: string): Promise<void> { export async function indexFilesAsync(index: any, dirName: string, settings: Settings): Promise<void> {
fs.readdir(dirName, async (err: string, items: string[]) => { fs.readdir(dirName, async (err: string, items: string[]) => {
for (const fileName of items) { for (const fileName of items) {
await processMdxAsync(index, dirName, fileName); await processMdxAsync(index, dirName, fileName, settings);
} }
}); });
} }

View File

@@ -0,0 +1,21 @@
import { adminClient, searchIndices, settings } from '../ts/utils/algolia_search';
import { indexFilesAsync } from './algolia_helpers';
// Get args after command (i.e. ts-node) and path to file (i.e. ./index.ts)
const args = process.argv.slice(2);
function processIndices(indices: string[]): void {
for (const indexName of indices) {
const index = adminClient.initIndex(searchIndices[indexName]);
indexFilesAsync(index, indexName, settings[indexName]);
}
}
if (args.length > 0) {
// Use args given to process and push to algolia
processIndices(args);
} else {
// Process and push all indices
processIndices(Object.getOwnPropertyNames(searchIndices));
}

View File

@@ -1,8 +0,0 @@
import { adminClient, searchIndex, settings } from '../ts/utils/algolia_search';
import { indexFilesAsync, setIndexSettings } from './helpers';
const indexName = 'guides';
const index = adminClient.initIndex(searchIndex[indexName]);
setIndexSettings(index, settings[indexName]);
indexFilesAsync(index, indexName);

View File

@@ -1,8 +0,0 @@
import { adminClient, searchIndex, settings } from '../ts/utils/algolia_search';
import { indexFilesAsync, setIndexSettings } from './helpers';
const indexName = 'tools';
const index = adminClient.initIndex(searchIndex[indexName]);
setIndexSettings(index, settings[indexName]);
indexFilesAsync(index, indexName);

View File

@@ -7,7 +7,7 @@ import { Link } from '@0x/react-shared';
import { AutocompleteOverlay } from 'ts/components/docs/search/autocomplete_overlay'; import { AutocompleteOverlay } from 'ts/components/docs/search/autocomplete_overlay';
import { AutocompleteWrapper } from 'ts/components/docs/search/autocomplete_wrapper'; import { AutocompleteWrapper } from 'ts/components/docs/search/autocomplete_wrapper';
import { searchIndex } from 'ts/utils/algolia_search'; import { searchIndices } from 'ts/utils/algolia_search';
interface IHit { interface IHit {
description: string; description: string;
@@ -87,7 +87,7 @@ const CustomAutoComplete: React.FC<IAutoCompleteProps> = ({ isHome = false, hits
}; };
const renderSectionTitle = (section: any): React.ReactNode => { const renderSectionTitle = (section: any): React.ReactNode => {
const { tools, guides } = searchIndex; const { tools, guides } = searchIndices;
const titles: { [key: string]: string } = { const titles: { [key: string]: string } = {
[tools]: 'Tools', [tools]: 'Tools',

View File

@@ -3,17 +3,17 @@ import { Configure, Index, InstantSearch } from 'react-instantsearch-dom';
import { AutoComplete } from 'ts/components/docs/search/autocomplete'; import { AutoComplete } from 'ts/components/docs/search/autocomplete';
import { searchClient, searchIndex } from 'ts/utils/algolia_search'; import { searchClient, searchIndices } from 'ts/utils/algolia_search';
interface ISearchInputProps { interface ISearchInputProps {
isHome?: boolean; isHome?: boolean;
} }
export const SearchInput: React.FC<ISearchInputProps> = ({ isHome }) => ( export const SearchInput: React.FC<ISearchInputProps> = ({ isHome }) => (
<InstantSearch searchClient={searchClient} indexName={searchIndex.tools}> <InstantSearch searchClient={searchClient} indexName={searchIndices.tools}>
<AutoComplete isHome={isHome} /> <AutoComplete isHome={isHome} />
<Configure hitsPerPage={5} distinct={true} /> <Configure hitsPerPage={5} distinct={true} />
<Index indexName={searchIndex.tools} /> <Index indexName={searchIndices.tools} />
<Index indexName={searchIndex.guides} /> <Index indexName={searchIndices.guides} />
</InstantSearch> </InstantSearch>
); );

View File

@@ -7,11 +7,11 @@ import { Resource } from 'ts/components/docs/resource/resource';
import { Separator } from 'ts/components/docs/separator'; import { Separator } from 'ts/components/docs/separator';
import { Filters } from 'ts/components/docs/sidebar/filters'; import { Filters } from 'ts/components/docs/sidebar/filters';
import { searchClient, searchIndex } from 'ts/utils/algolia_search'; import { searchClient, searchIndices } from 'ts/utils/algolia_search';
export const DocsGuides: React.FC = () => ( export const DocsGuides: React.FC = () => (
<DocsPageLayout title="Guides"> <DocsPageLayout title="Guides">
<InstantSearch searchClient={searchClient} indexName={searchIndex.guides}> <InstantSearch searchClient={searchClient} indexName={searchIndices.guides}>
<Columns> <Columns>
<Filters filters={filters} /> <Filters filters={filters} />
<Separator /> <Separator />

View File

@@ -13,7 +13,7 @@ import { ContentWrapper } from 'ts/components/docs/layout/content_wrapper';
import { DocsPageLayout } from 'ts/components/docs/layout/docs_page_layout'; import { DocsPageLayout } from 'ts/components/docs/layout/docs_page_layout';
import { Separator } from 'ts/components/docs/separator'; import { Separator } from 'ts/components/docs/separator';
import { searchClient, searchIndex } from 'ts/utils/algolia_search'; import { searchClient, searchIndices } from 'ts/utils/algolia_search';
interface IHitsProps { interface IHitsProps {
hits: IHit[]; hits: IHit[];
@@ -37,7 +37,7 @@ interface IHit {
export const DocsTools: React.FC = () => { export const DocsTools: React.FC = () => {
return ( return (
<DocsPageLayout title="Tools"> <DocsPageLayout title="Tools">
<InstantSearch searchClient={searchClient} indexName={searchIndex.tools}> <InstantSearch searchClient={searchClient} indexName={searchIndices.tools}>
<Columns> <Columns>
<Filters filters={filters} /> <Filters filters={filters} />
<Separator /> <Separator />

View File

@@ -5,10 +5,27 @@ const ALGOLIA_CLIENT_API_KEY = '4c367b8cc6d6e175ae537cc61e4d8dfd';
// @TODO: Move the following somewhere safe / out of the repo // @TODO: Move the following somewhere safe / out of the repo
const ALGOLIA_ADMIN_API_KEY = 'ccc472dee2aa991ca4bc935975e76b5d'; const ALGOLIA_ADMIN_API_KEY = 'ccc472dee2aa991ca4bc935975e76b5d';
interface ISearchIndices {
[index: string]: string;
}
interface ISettingsIndex {
[index: string]: Settings;
}
interface Settings {
distinct: boolean;
attributeForDistinct: string;
attributesForFaceting: string[];
attributesToSnippet: string[];
searchableAttributes: string[];
snippetEllipsisText: string;
}
export const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_CLIENT_API_KEY); export const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_CLIENT_API_KEY);
export const adminClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_ADMIN_API_KEY); export const adminClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_ADMIN_API_KEY);
export const searchIndex = { export const searchIndices: ISearchIndices = {
guides: '0x_guides_test', guides: '0x_guides_test',
tools: '0x_tools_test', tools: '0x_tools_test',
}; };
@@ -21,7 +38,7 @@ const sharedSettings = {
snippetEllipsisText: '…', snippetEllipsisText: '…',
}; };
export const settings = { export const settings: ISettingsIndex = {
guides: { guides: {
...sharedSettings, ...sharedSettings,
attributesForFaceting: ['topics', 'difficulty'], attributesForFaceting: ['topics', 'difficulty'],