search: answer JMAP searches from an index of the corpus

Typing "fede" matched Federico's mail only among the threads loaded; the server matches whole words, so asking it found nothing more. Index the corpus in memory as it is read and as messages are kept: each lowercased word and the messages it is in, by field. A search finds the messages that have, for each word typed, a word starting with it, and ranks their threads by where it matched (subject, sender, recipients, files, text, then quoted text), a whole word counting twice a word's start, then by date. Threads are numbered as they are indexed, so ranking is an array and a sort rather than string hashing: on 92,000 synthetic messages of 500 words, every search took under 10 ms, and indexing about 15 s, off the app's thread. Once the backfill has kept every message, the JMAP session answers a search from the index, reading only the threads of each page not loaded. A search naming labels or flags, which the corpus does not keep (label:, is:, in:anywhere, "me"), still goes to the server.


Author rockorager.dev
Date Commit Parent 8c562024
+549 -23
6 changed files
+549 -23
6 changed files