搜索引擎中索引的好坏直接影响着搜索引擎的性能,最终影响到用户的体验,可见索引的重要性。
今天我们就来谈谈索引技术。谈到索引大家第一想到的是倒排索引,的确倒排在全文检索中的优势,在搜索引擎中的大量使用令它声名鹊起。所以在此就以倒 排进行分析。但是除了倒排索引外还有很多的索引方式,如静态索引方式有:位图、签名文件、倒排等;动态索引有:B树、B+树等等。
搜索引擎之所以大量使用倒排作为它内部的索引结构,本人觉得主要有两个原因:
1、容易实现、存储简单,更重要的一点是方便进行rank排序,当然还包括倒排列表可以压缩。像位图和签名文件就没有rank排序和压缩的优势。
2、方便查询结果处理,很容易实现布尔计算。现今的主流搜索引擎用的本质计算都属于布尔计算。如要查询包含A和B的文档,其实质是先找出包含A的文档列表,再找出包含B的文档列表,最后把那些既在列表A又在列表B的文档作为结果返回。其实质就是进行一个合取查询操作。
下面就以简单的程序方式来说明到排索引(基于内存的索引)的原理:
import
import
import
import
import
import
import
import
public class
/**
* 字典.<术语,倒排列表>
*/
private static Map<String,Set<Node>> dictionary = new
private static Pattern extraPattern = Pattern.compile("(//w+)");
public void
if (term != null) {
//大小写折叠
if
new
}
}
}
//建立倒排列表
private void index(String term,Integer doc,int
term = term.toLowerCase();
Set<Node> reverseList = dictionary.get(term);
if(reverseList !=null){
new
}
}
/**
* 这一步其实属于关键词抽取,在搜索引擎中由专门的抽取程序处理。
* @param txt 要建索引的文档
* @param doc 文档编号
*/
public void
if(txt == null)
return;
Matcher m = extraPattern.matcher(txt);
new
while(m.find()){
//算没个词条的频率,准备使用坐标匹配的rank
1);
if(! map.containsKey(t))
1);
else
1);
}
for
index(entry.getKey(),doc,entry.getValue());
}
}
/*
* 对查询结果进行布尔查询中的合取操作
*/
private
if(queryResult == null || queryResult.size() == 0){
return new
}
null;
for
//选择元素最少的查询列表,这样可以减少合取时计算量
if(min == null){
min = set;
else if(min.size() > set.size()){
min = set;
}
}
new
for
ret.add(n);
}
for
for
if(min == set){
continue;
else if(! set.contains(n)){
//如果在此查询词中不包括文档号,则直接删除此文档
break;
}
}
}
return
}
/**
* 查询包含查询术语query的文档
* @param query
* @return 文档列表
*/
public
if(query ==null)
return new Node[0];
query = query.trim().toLowerCase();
if(query.length() ==0)
return new Node[0];
"//s+");
new
for
Set<Node> reverseList = dictionary.get(t);
if (reverseList != null) {
queryResults.add(reverseList);
}
}
Set<Node> result = mergeResult(queryResults);
return result.toArray(new
}
/**
* @param args
*/
public static void
"This distribution includes cryptographic software. The country in /n"
"which you currently reside may have restrictions on the import, /n"
"possession, use, and/or re-export to another country, of /n"
"encryption software. BEFORE using any encryption software, please /n"
"check your country's laws, regulations and policies concerning the /n"
"import, possession, or use, and re-export of encryption software, to /n"
"see if this is permitted. See <http://www.wassenaar.org/> for more /n"
"information. /n"
"The U.S. Government Department of Commerce, Bureau of Industry and /n"
"Security (BIS), has classified this software as Export Commodity /n"
"Control Number (ECCN) 5D002.C.1, which includes information security /n"
"software using or performing cryptographic functions with asymmetric /n"
"algorithms. The form and manner of this Apache Software Foundation /n"
"distribution makes it eligible for export under the License Exception /n"
"ENC Technology Software Unrestricted (TSU) exception (see the BIS /n"
"Export Administration Regulations, Section 740.13) for both object /n"
"code and source code. /n"
"The following provides more details on the included cryptographic /n"
"software: /n"
" Hadoop Core uses the SSL libraries from the Jetty project written /n"
"by mortbay.org. /n"
/*
* 要建索引的文档,每一行为一个文档
*/
"/n");
//字典文件
"the provides details Commerce Security Commodity Hadoop libraries TSU laws distribution software country reside import possession".split("//s+");
new
for
//构建字典
index.addTerm(term);
}
int sno = 0;
for(String doc:docs){
//建立索引
index.buildIndex(doc, sno++);
}
"please type query words:");
while(true){
new
String query = in.nextLine();
if("exit".equalsIgnoreCase(query))
break;
"query:"+query);
Node[] dosList = index.retrieve(query);
if(dosList.length ==0
{
"there are not docs relate to query words '%s'",query);
continue;
}
for(Node dc:dosList){
"[%d,%d] %s/n", dc.doc, dc.frequency, docs[dc.doc]);
}
}
}
static class Node implements
private
private int
@Override
public int
return
}
public Node(int doc,int
this.doc = doc;
this.frequency = f;
}
public
return
}
public int
return
}
}
}
说明:
1、索引必须要有一个字典存在,字典就是一些术语的集合.如dog、cat、hotel、beijing .....索引引擎中的字典一般来自公共知识库,商场、娱乐新闻、电影简报等等。
2、索引以索引文件的形式存在磁盘上,在使用的时候加载进内存,或者部分加载进内存,大多数情况下内存不够存放所有的索引,所以有时候索引会进行压 缩存储,字典文件和倒排列表都有相应的压缩方式。如字典中常用的压缩有前缀压缩、最小完美hash、基于磁盘的字典等;到排列表压缩有:一元编码等
3、这里给出的索引方式为基于内存的索引,在索引数据量大时不适用。当然这里把它放在内存是没问题,毕竟才一篇文章,文章的每一行作为一个文档对待。
4、真正的搜索引擎当到索引这一步时所有的数据都已经就绪,关键词的抽取(extract)、术语的权重等等。