indexer.ts (2283B)
1 import { Hits, MeiliSearch } from 'meilisearch'; 2 import Config from './config.js'; 3 4 const config = new Config(); 5 6 /* This is the indexer. It is a wrapper around orama. 7 * 8 * It makes sure that the database is persisted on inserts and updates. 9 * It also makes sure that the database is loaded on startup. 10 * It also ensures the correct search is used. 11 * 12 */ 13 export default class Indexer { 14 private readonly client = new MeiliSearch({ 15 host: config.meiliSearchHost, 16 apiKey: config.meiliSearchKey 17 }); 18 private readonly textIndex = this.client.index('text'); 19 20 constructor() { 21 } 22 23 // TODO: Properly type the data 24 public async insert(data: Record<string, any>) { 25 return await this.textIndex.addDocuments([data], { primaryKey: 'id' }); 26 } 27 28 public async search(query: string, room_id?: string, sender?: string, limit?: number) { 29 await this.textIndex.updateSearchableAttributes(['content.body', "sender", "content.m.mentions.user_id", "room_name"]); 30 await this.textIndex.updateFilterableAttributes([ 31 'id', 32 'sender', 33 'room_id', 34 'origin_server_ts' 35 ]) 36 37 let results: Hits<Record<string, any>> = []; 38 let page = 1; 39 40 let filter = ""; 41 if (room_id) { 42 filter += `room_id = "${room_id}"`; 43 } 44 if (sender) { 45 if (filter != "") { 46 filter += " AND "; 47 } 48 filter += `sender = "${sender}"`; 49 } 50 let filters; 51 if (filter != "") { 52 filters = [filter] 53 } 54 55 // Keep searching until we got everything 56 let response = await this.textIndex.search(query, { page: page, filter: filters }); 57 results = results.concat(response.hits); 58 while (page < response.totalPages) { 59 response = await this.textIndex.search(query, { page: page, filter: filters }); 60 results = results.concat(response.hits); 61 page++; 62 } 63 64 if (limit) { 65 results = results.slice(0, limit); 66 } 67 68 return { hits: results, estimatedTotalHits: results.length }; 69 } 70 71 public async delete(event_id: string) { 72 return await this.textIndex.deleteDocument(event_id); 73 } 74 }