文档搜索引擎模块划分(第一篇)见系列文章:
索引模块程序见下文:
本文为搜索模块程序篇。
目录
[4.1 DocSearcher类](#4.1 DocSearcher类)
[4.1.1 DocSearcher类实现逻辑](#4.1.1 DocSearcher类实现逻辑)
[4.1.2 DocSearcher类程序](#4.1.2 DocSearcher类程序)
[4.2 封装Result类](#4.2 封装Result类)
4.1 DocSearcher类
4.1.1 DocSearcher类实现逻辑
分词:对查询词query进行分词;
触发:针对分词结果查倒排索引;
排序:针对出发结果按照权重降序排序;
包装结果:针对排序的结果查正排索引,包装要返回的数据
4.1.2 DocSearcher类程序
java
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
// 实现搜索过程
public class DocSearcher {
// 定义索引对象实例,并完成索引加载(使用构造方法完成)
private Index index = new Index();
public DocSearcher(){
index.load();
}
public List<Result> search(String query){
// 1. 对查询词query进行分词
List<Term> terms= ToAnalysis.parse(query).getTerms();
// 2. 针对分词结果查倒排索引
List<Weight> allTermResult = new ArrayList<>();
for(Term term: terms){
String word = term.getName();
List<Weight> invertedList = index.getInverted(word);
// 词在文档中不存在,则跳过本次循环
if(invertedList == null)
continue;
allTermResult.addAll(invertedList);
}
// 3. 针对出发结果按照权重降序排序
allTermResult.sort(new Comparator<Weight>() {
@Override
public int compare(Weight o1, Weight o2) {
return o2.getWeight()-o1.getWeight(); // 降序
// 若为升序,则返回o1.getWeight()-o2.getWeight()
}
});
// 4. 针对排序的结果查正排索引,包装要返回的数据
List<Result> results = new ArrayList<>();
for(Weight weight: allTermResult){
DocInfo docInfo = index.getDocInfo(weight.getDocId());
Result result = new Result();
result.setTitle(docInfo.getTitle());
result.setUrl(docInfo.getUrl());
// 描述是正文的一段摘要
result.setDesc(GenDesc(docInfo.getContent(),terms));
results.add(result);
}
return results;
}
}
由于desc描述是content正文的一段摘要,故而单独封装一个Genedsc方法:
java
// 根据正文生成描述
private String GenDesc(String content, List<Term> terms){
int firstPos = -1;
// 在content中查找存在的分词结果
for(Term term: terms){
String word = term.getName();
firstPos = content.toLowerCase().indexOf(" "+word+" ");
if(firstPos >= 0)
break;
}
if(firstPos == -1){
// 所有分词结果都不在正文结果中
// 直接取正文前160个字符作为描述
return content.substring(0, 160)+"...";
}
// 从firstPos作为基准,向前找160个字符作为描述的起始位置
String desc = "";
int descBeg = firstPos < 60 ? 0 : firstPos - 60;
if(descBeg + 160 > content.length()){
desc = content.substring(descBeg);
}else{
desc = content.substring(descBeg, descBeg+160)+"...";
}
return desc;
}
4.2 封装Result类
java
// 表示搜索结果
public class Result {
private String title;
private String url;
// 描述是正文的一段摘要
private String desc;
// 省略Getter和Setter方法
@Override
public String toString() {
return "Result{" +
"title='" + title + '\'' +
", url='" + url + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
注:在main方法中需要测试DocSearcher根据查询词查询功能,需要输出描述,故而需要重写toString方法。