Created
March 8, 2023 18:09
-
-
Save tmilewski/805bff212a130b2e4532a24169160494 to your computer and use it in GitHub Desktop.
Quick and dirty pseudo-code for a typed search (Algolia) index
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { SearchIndex } from './search-index.ts' | |
import { SearchService } from './search-service.ts' | |
// ========================================================== | |
// Index Contents Shape | |
// ========================================================== | |
export interface Collab { | |
id: string | |
name: string | |
description: string | |
profileId: string | |
// etc... | |
} | |
// ========================================================== | |
// Generic Usage | |
// ========================================================== | |
const searchService = new SearchService() | |
export const collabsIdx = new SearchIndex<Collab>(searchService, 'collabs') | |
collabsIdx.save({ id: '123', name: 'test1', description: 'test1', profileId: 'abc' }) | |
collabsIdx.save<Partial<Collab>>({ id: '000', name: 'test1', profileId: 'yxz' }) // Override input type | |
collabsIdx.saveMany([ | |
{ id: '456', name: 'test2', description: 'test2', profileId: 'def' }, | |
{ id: '789', name: 'test3', description: 'test3', profileId: 'ghi' }, | |
]) | |
collabsIdx.get('123') | |
collabsIdx.getMany(['456', '789']) | |
collabsIdx.delete('123') | |
// ========================================================== | |
// Usage via `extends` | |
// ========================================================== | |
export class CollabsSearchIndex extends SearchIndex<Collab> { | |
constructor(protected service: AlgoliaService) { | |
super(service, 'collabs') | |
} | |
} | |
const collabsIdxExt = new CollabsSearchIndex(searchService) | |
collabsIdxExt.save({ id: '123', name: 'test1', description: 'test1', profileId: 'abc' }) | |
collabsIdxExt.save<Partial<Collab>>({ id: '000', name: 'test1', profileId: 'yxz' }) // Override input type | |
collabsIdxExt.saveMany([ | |
{ id: '456', name: 'test2', description: 'test2', profileId: 'def' }, | |
{ id: '789', name: 'test3', description: 'test3', profileId: 'ghi' }, | |
]) | |
collabsIdxExt.get('123') | |
collabsIdxExt.getMany(['456', '789']) | |
collabsIdxExt.delete('123') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { type SearchIndex as AlgoliaSearchIndex } from 'algoliasearch' | |
// ========================================================== | |
// Generic Index (allowing for type safety) | |
// ========================================================== | |
// TODO: Create "generic" responses from the Algolia specific ones | |
export class SearchIndex<T extends Record<string, any>> { | |
protected readonly index: AlgoliaSearchIndex | |
constructor(protected service: AlgoliaService, protected readonly indexName: string) { | |
this.index = this.service.client.initIndex(indexName) | |
} | |
async get<R = T>(id: string) { | |
return this.index.getObject<R>(id) | |
} | |
async getMany<R = T>(ids: string[]) { | |
return this.index.getObjects<R>(ids) | |
} | |
async save<R = T>(object: Readonly<R>) { | |
return this.index.saveObject(object) | |
} | |
async saveMany<R = T>(objects: ReadonlyArray<Readonly<R>>) { | |
return this.index.saveObjects(objects) | |
} | |
async delete(id: string) { | |
return this.index.deleteObject(id) | |
} | |
async deleteBy(filters: string) { | |
return this.index.deleteBy({ filters }) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import algoliasearch, { type SearchClient } from 'algoliasearch' | |
// ========================================================== | |
// Generic Search Service | |
// ========================================================== | |
class SearchService { | |
readonly client: SearchClient | |
// TODO: Use actual config; Validate/parse with Zod | |
constructor(id = process.env.ALGOLIA_APP_ID, key = process.env.ALGOLIA_API_KEY) { | |
if (!id) throw new Error('App ID not specified') | |
if (!key) throw new Error('API Key not specified') | |
this.client = algoliasearch(id, key) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment