作者:来自 Elastic David Pilato
到目前为止,我们已经看到如何针对你映射的任意 field 运行 search query。任何熟悉 search engine 的人都知道下一步是什么: autocomplete ,这样 index 就可以帮助你找到正确的 query。
Autocomplete 有自己的 artifact:
`
1. <dependency>
2. <groupId>org.apache.lucene</groupId>
3. <artifactId>lucene-suggest</artifactId>
4. <version>10.5.1</version>
5. </dependency>
`AI写代码
第二个 Directory
AnalyzingInfixSuggester 并不是针对 track index 的IndexSearcher。它是一个拥有自己 Directory的 dictionary。使用与之前相同的 analyzer,这样 prefixes 才能匹配 titles 的 tokenization 方式:
`
1. Directory suggestionDirectory = new ByteBuffersDirectory();
2. AnalyzingInfixSuggester suggester = new AnalyzingInfixSuggester(
3. suggestionDirectory, analyzer);
4. suggester.build(new TrackSuggestionInputIterator(tracks.values()));
`AI写代码
将它放在 track writer 旁边,在 rebuild / upsert 时使用相同的 write lock。对 infix suggester 执行增量 delete 比较麻烦;对于几千个 beans,可以在每次 mutation 后重建 dictionary。
输入 “club”
输入 prefix club。将鼠标悬停在某一行上,可以看到lookup()→highlightKey、field、FILTER chip。
`
1. List<Lookup.LookupResult> matches =
2. suggester.lookup("club", Set.of(), 10, true, true);
3. Lookup.LookupResult match = matches.get(0);
4. String text = match.key.toString();
5. // "Club House"
6. String field = match.payload.utf8ToString();
7. // "genre"
8. String highlight = match.highlightKey.toString();
9. // "<b>Club</b> House"
`AI写代码
这意味着第一个 suggestion 是来自genrefield 的Club House,可以向用户呈现为:
Club House。
使用 suggestion 进行过滤
选择Club House(field = "genre")后,可以调用你的后端 search API:/tracks?genre=Club House,并更新 UI 以反映所选的 filter chip。
如果你希望 suggestions 遵循当前的 filter set,请修改调用:
`
1. List<Track> scoped = search.filter(corpus, "", filters, mustNots);
2. List<TrackSuggestion> hits = index.suggest(prefix, scoped);
`AI写代码
filter(..., "", filters, mustNots)会应用当前已经启用的 chips,并使用一个空的 query string。然后,suggest(prefix, scoped)只会在这个子集内查找,因此club不会推荐那些已被这些 chips 排除的 genre。
完整 demo 位于 GitHub:lucene-search-tracks。