|
1 | 1 | package com.haroldadmin.lucilla.core |
2 | 2 |
|
| 3 | +import com.haroldadmin.lucilla.core.rank.ld |
3 | 4 | import com.haroldadmin.lucilla.core.rank.tfIdf |
4 | 5 | import com.haroldadmin.lucilla.ir.Posting |
5 | 6 | import com.haroldadmin.lucilla.ir.extractDocumentId |
@@ -32,6 +33,11 @@ public data class SearchResult( |
32 | 33 | val matchTerm: String, |
33 | 34 | ) |
34 | 35 |
|
| 36 | +public data class AutocompleteSuggestion( |
| 37 | + val score: Double, |
| 38 | + val suggestion: String, |
| 39 | +) |
| 40 | + |
35 | 41 | /** |
36 | 42 | * Alias for a token in a document |
37 | 43 | */ |
@@ -239,10 +245,48 @@ public class FtsIndex<DocType : Any>( |
239 | 245 | } |
240 | 246 | } |
241 | 247 |
|
242 | | - results.sortByDescending { result -> result.score } |
| 248 | + results.sortBy { result -> result.score } |
243 | 249 | return results |
244 | 250 | } |
245 | 251 |
|
| 252 | + /** |
| 253 | + * Fetches autocompletion suggestions for the given query. |
| 254 | + * |
| 255 | + * An autocompletion suggestion is a term present in the index that |
| 256 | + * has the same prefix as the given search query. The results are sorted |
| 257 | + * in order of their relevance score. |
| 258 | + * e.g. "foo" -> "fool", "foot", "football" |
| 259 | + * |
| 260 | + * **Autocompletion suggestions can be unexpected if stemming is a part |
| 261 | + * of your text processing pipeline.** |
| 262 | + * |
| 263 | + * For example, the Porter stemmer stems "football" to "footbal". Therefore, |
| 264 | + * even if your input text contains the word "football", you will see "footbal" |
| 265 | + * as an autocompletion suggestion instead. |
| 266 | + * |
| 267 | + * The simplest way around this is to use a [Pipeline] that does not contain |
| 268 | + * a stemming step. Alternatively you can use a custom stemmer that emits |
| 269 | + * both the original word and its stemmed variant to ensure the original |
| 270 | + * word appears in the suggestions. |
| 271 | + * |
| 272 | + * *Expect the autocompletion ranking algorithm to change in future releases* |
| 273 | + * |
| 274 | + * @param query The search query to fetch autocompletion suggestions for |
| 275 | + * @return List of autocompletion suggestions, sorted by their scores |
| 276 | + */ |
| 277 | + public fun autocomplete(query: String): List<AutocompleteSuggestion> { |
| 278 | + val suggestions = _index.prefixMap(query).keys |
| 279 | + .fold(mutableListOf<AutocompleteSuggestion>()) { suggestions, prefixKey -> |
| 280 | + val score = ld(query, prefixKey).toDouble() / prefixKey.length |
| 281 | + val suggestion = AutocompleteSuggestion(score, prefixKey) |
| 282 | + suggestions.apply { add(suggestion) } |
| 283 | + } |
| 284 | + |
| 285 | + suggestions.sortByDescending { it.score } |
| 286 | + |
| 287 | + return suggestions |
| 288 | + } |
| 289 | + |
246 | 290 | /** |
247 | 291 | * Clears all documents added to the FTS index |
248 | 292 | */ |
|
0 commit comments