一、什么是全文检索?
全文检索是一种将文件中所有文本与检索项匹配的文字资料检索方法。
1、只处理文本,不处理语义
2、搜索时英文不区分大小写
3、结果列表有相关度排序
全文检索根据应用场景可以简单分为站内搜索和垂直搜索。
二、全文检索与数据库搜索的区别?
数据库的搜索:
类似:select * from 表名 where 字段名 like “%关键字%”;
例如:select * from article where content like “%here%”;
结果: where here shere
缺点:
1、搜索效果比较差
2、在搜索的结果中,有大量的数据被搜索出来,有很多数据是没有用的
3、查询速度在大量数据的情况下是很难做到快速的。(sql语句中like速率最低)
全文检索:
1、搜索结果按相关度排序:意味着只有前几个页面对于用户来说是比较有用的,其他的结果与用户想要的答案很可能相差甚远。数据库搜索是做不到相关度排序的。
2、因为全文检索是采用索引的方式,所以在速度上肯定比数据库方式like要快。
三、互联网搜索结构框架
说明:
1、当用户打开www.baidu.com网页搜索某些数据的时候,不是直接找的网页,而是找的百度的索引库。索引库里包含的内容有索引号和摘要。当我们打开www.baidu.com时,看到的就是摘要的内容。
2、百度的索引库的索引和互联网的某一个网站对应。
3、当用户输入要查询的关键字,返回的页面首先是从索引库中得到的。
4、点击每一个搜索出来的内容进行相关网页查找,这个时候才找的是互联网中的网页。
互联网搜索引擎的技术难点就是如何把庞大的、杂乱无章的数据放到索引库中让客户快速的检索出来。
四、lucene的大致结构框架
说明:
1、在数据库中,数据库中的数据文件存储在磁盘上。索引库也是同样,索引库中的索引数据也在磁盘上存在,我们用Directory这个类来描述。
2、我们可以通过API来实现对索引库的增、删、改、查的操作。
3、在数据库中,各种数据形式都可以概括为一种:表。在索引库中,各种数据形式也可以抽象出一种数据格式为Document。
4、Document的结构为:Document(List<Field>)
5、Field里存放一个键值对。键值对都为字符串的形式。
6、对索引库中索引的操作实际上也就是对Document的操作。
五、第一个lucene程序
1、准备lucene的开发环境
搭建lucene的开发环境,要准备lucene的jar包,要加入的jar包至少有:
1)lucene-core-3.1.0.jar (核心包)
2)lucene-analyzers-3.1.0.jar (分词器)
3)lucene-highlighter-3.1.0.jar (高亮器)
4)lucene-memory-3.1.0.jar (内存器)
2、建立索引
示意图:
开发步骤:
1)创建IndexWriter对象
2)把JavaBean转化为Document
3)利用IndexWriter.addDocument方法增加索引
4)关闭资源
代码:
/*
* 创建索引
* */
@Test
public void createIndex() throws Exception{
/*
* 开发步骤:
* 1、创建一个article对象
* 2、把article对象转换成document对象
* 3、创建一个IndexWriter对象
* 4、把document对象加入到索引库中
* */
//1、创建一个article对象
Article article = new Article();
article.setId(1001L);
article.setTitle("lucene瞎搞的");
article.setContext("使用lucene技术可以实现全文检索的功能,著名的搜索引擎有百度、google.");
//2、把article对象转换成document对象
Document document = new Document();
/*
* 第一个参数:放入到索引库中的name的名称“id”
* 第二个参数:放入到索引库中的value
* 第三个参数:是否向内容库中存储(YES:存储 ; NO:不存储)
* 第三个参数:是否向目录库中存储(NO:不存储; NOT_ANALYZED:存储,但是不分词; ANALYZED:存储,分词)
* */
Field idField = new Field("id", article.getId().toString(), Store.YES, Index.NOT_ANALYZED);
Field titleField = new Field("title", article.getTitle().toString(), Store.YES, Index.NOT_ANALYZED);
Field contextField = new Field("context", article.getContext().toString(), Store.YES, Index.NOT_ANALYZED);
document.add(idField);
document.add(titleField);
document.add(contextField);
//3、创建一个IndexWriter对象
Directory directory = FSDirectory.open(new File("./indexDir")); //索引库
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30); //分词器
/*
* directory:指向了索引库的路径"./indexDir"
* analyzer:分词器,把title、context的内容分词后放入到目录中
* MaxFieldLength:限制每一个字段在索引库中存放的大小
* */
IndexWriter indexWrite = new IndexWriter(directory, analyzer, MaxFieldLength.LIMITED);
//4、把document对象加入到索引库中
indexWrite.addDocument(document);
indexWrite.commit();
indexWrite.close();
}
3、搜索
示意图:
开发步骤:
1)创建IndexSearch
2)创建Query对象
3)进行搜索
4)获得总结果数和前N行记录ID列表
5)根据目录ID列表把Document转为为JavaBean并放入集合中。
6)循环出要检索的内容
代码:
/*
* 搜索
* */
@Test
public void searchIndex() throws Exception{
Directory directory = FSDirectory.open(new File("./indexDir")); //索引库
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30); //分词器
//创建一个IndexSearcher对象
IndexSearcher indexSearcher = new IndexSearcher(directory);
/*
* 第一个参数:版本号
* 第二个参数:在哪个字段进行检索
* 第三个参数:分词器,在调用QueryParser的parse()的时候,需要对参数再次进行分词
* */
QueryParser queryParser = new QueryParser(Version.LUCENE_30,"title",analyzer);
Query query = queryParser.parse("lucene");
/*
* 第一个参数:包含了一个分词器和一个关键词
* 第二个参数:查找前n条记录
* TopDocs == top document(前一些document)
* */
TopDocs topDocs = indexSearcher.search(query, 2);
int count = topDocs.totalHits; //根据关键词检索出来的总记录数
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
List<Article> articles = new ArrayList<Article>();
for(ScoreDoc scoreDoc : scoreDocs){
float score = scoreDoc.score; //相关度得分
Document document = indexSearcher.doc(scoreDoc.doc);
Article article = new Article();
article.setId(Long.parseLong(document.get("id")));
article.setTitle(document.get("title"));
article.setContext(document.get("context"));
articles.add(article);
}
for(Article article : articles){
System.out.println(article.getId());
System.out.println(article.getTitle());
System.out.println(article.getContext());
}
}
六、保持数据库与索引库的同步
示意图:
说明:
在一个系统中,如果索引功能存在,那么数据库和索引库应该是同时存在的。这个时候需要保证索引库的数据和数据库中的数据保持一致性。可以在对数据库进行增、删、改操作的同时对索引库也进行相应的操作。这样就可以保证数据库与索引库的一致性。