最近有在研究希望能够实现一个搜索框的智能搜索提示,几经辗转找到了这个包。
<!-- https://mvnrepository.com/artifact/org.nlpcn/nlp-lang -->
<groupId>org.nlpcn</groupId>
<artifactId>nlp-lang</artifactId>
<version>1.7.9</version>
基于这个包可以帮助我们实现一个基于内存的关键字提示功能。
介绍
核心类为 org.nlpcn.commons.lang.index.MemoryIndex
,通过这个类可以帮助我们实现一个简单的倒排索引。在不考虑性能的情况下,这个类可以帮助我们实现一个开箱即用的倒排索引。
这里我们主要是针对字符串实现智能提示,编写一个封装:
public class SearchTemplate {
/**
* 索引
*/
private final MemoryIndex<String> index;
public SearchTemplate() {
index = new MemoryIndex<>();
}
/**
* 获取提示
* @param key
* @return
*/
public Collection<String> suggest(String key) {
// 智能提示,允许错别字
return index.smartSuggest(key);
}
/**
* 添加记录
* @param record 记录
*/
public void add(String record) {
// 获取记录的拼音,并为记录索引
String pinyin = String.join("", Pinyin.pinyin(record));
// 获取记录的首字母,并为记录索引
String firstChar = String.join("", Pinyin.firstChar(record));
index.addItem(record, record, pinyin, firstChar);
}
}
然后在方法中添加记录,后调用方法suggest
获取建议:
public static void main(String[] args) {
List<String> list = Arrays.asList("中国", "中华人民共和国", "美国", "我爱中国", "我是中国人", "漂亮国", "中世纪的世界", "天堂");
SearchTemplate searchTemplate = new SearchTemplate();
// 将记录遍历并添加的倒排索引中
list.forEach(searchTemplate::add);
// 获取搜索结果
System.out.println(searchTemplate.suggest("zhong")); //[中国, 我爱中国, 我是中国人, 中世纪的世界, 中华人民共和国]
System.out.println(searchTemplate.suggest("国")); //[中国, 美国, 漂亮国, 我爱中国, 我是中国人, 中华人民共和国, 天堂, 中世纪的世界]
System.out.println(searchTemplate.suggest("我")); //[我爱中国, 我是中国人]
System.out.println(searchTemplate.suggest("wa")); //[我爱中国]
System.out.println(searchTemplate.suggest("shijie")); //[中世纪的世界]
}
由于我在封装 MemoryIndex 的时候使用到了 smartSuggest
这个方法相较于 suggest
会通过查询的关键字尽可能的去匹配记录,所以你会发现有的结果与你查询的关键字完全对不上。
比如当我以 “国” 为关键字进行搜索的时候,会出现 “天堂”,“中世纪的世界” 这样记录中完全不包含 “国” 的记录。而 MemoryIndex 背后的搜索逻辑为:
- 使用 “国” 进行搜索,获取搜索到的结果
- 如果结果数量少于配置的数量,
则获取 “国” 的全拼 “guo” 并以此作为关键字获取相匹配的记录,
添加到搜索结果中 - 如果结果数量任然小于配置的数量
则获取 “国” 的拼音首字母 “g” 并以此作为关键字获取相匹配的记录
添加到搜索结果中
最终得到的结果就是由于记录 “天堂” 的全拼 “taintang” 和 “中世纪的世界” 的全拼 “zhongshijideshijei” 中包含 “g”,因此他们也在搜索结果中。
这里实现的功能其实很简单,而基于内存的搜索提示其实相当占用内存,比如上述的逻辑,我只输入了 7 条记录,但是 MemoryIndex
处理后保存的记录数就已经达到了惊人的 743 条结果了,这是因为MemoryIndex
会将每一种输入可能都处理成为了一条记录并保存下来,因此这样的搜索提示我们实际上是不能把它放到线上去的,但这种实现原理也为我们的开发提供了一种参考。
关于 nlp-lang
包,它提供了相当多的工具,能够帮助我们很好的处理文本,有机会可以好好研究下。
与这个包相关的还有一个
<groupId>org.ansj</groupId>
<artifactId>ansj_seg</artifactId>
<version>5.1.1</version>
这是一个可以用于实现中文分词的工具,日后也可以好好研究下。