Lucene与搜索引擎的区别
全文检索系统是按照全文检索理论建立起来的用于提供全文检索服务的软件系统。
全文检索系统是一个可以运行的系统,包括建立索引、处理查询返回结果集、增加索引、
优化索引结构等功能。例如:百度搜索、eclipse帮助搜索、淘宝网商品搜索。
搜索引擎是全文检索技术最主要的一个应用,例如百度。搜索引擎起源于传统的信息全文
检索理论,即计算机程序通过扫描每一篇文章中的每一个词,建立以词为单位的倒排文件,
检索程序根据检索词在每一篇文章中出现的频率和每一个检索词在一篇文章中出现的概率,
对包含这些检索词的文章进行排序,最后输出排序的结果。全文检索技术是搜索引擎的核心支撑技术。
Lucene和搜索引擎不同,Lucene是一套用java写的全文检索的工具包,为应用程序提供了很多个api接口去调用,
可以简单理解为是一套实现全文检索的类库,搜索引擎是一个全文检索系统,它是一个单独运行的软件。
1、全文检索,只检索文本
2、从信息源中拷贝到本地并进行加工,称为索引库(信息集合),搜索时从本地的信息集合中搜索
3、文本在建立索引和搜索时都会分词。(*都会使用分词器,并且应使用同一个分词器)
4、索引库索引的存放结构:倒排序索引 【索引库[索引表->][数据集合->存放数据*有文档内部编号* (首先找分词器在所有表中存储)]】
5、索引库是一组文件的集合:
(1)Directory 索引库位置
(2)Document 文档集合->中有set集合 set<Field> fields;
field的值是文本(如果是其他类型,如数字,日期都要转成文本) 是键值对,键是字符串
field name value
f1=new Field("title","XXX");
f2=new Field("body","XXX");
doc.add(f1);
doc.add(f2);
.........
6、HelloWorld程序(索引与搜索)
(1)添加jar包 核心、分词器、高亮器
(2)建立索引
(3)搜索
String filePath="文件目录";
String indexPath="索引库的目录";//路径\\两个反斜线
Analyzer analyzer=new StandarAnalyzer();//分词器
1、createIndex(){ //创建索引
//File file=new File("磁盘的文件路径");//路径\\两个反斜线
Document doc=File2DocumentUtils.file2Document(filepath);
//file->doc
//操作索引库(曾删改索引库)IndexWriter
IndexWriter indexwriter=new IndexWriter(indexPath{索引目录},analyzer,true,new MaxFieldLength(10000){MaxFieldLength.LLMITED 整形的最大值});//true 代表每次都创建,对前10000个词进行索引
indexWriter.addDocment(doc);//增加索引
indexWriter.close();//释放资源
}
// IndexSearcher 是用来在索引库中进行查询的
2、search(){//搜索
String queryStrng="document";
// 1、把要搜索的文本解析为query对象
QueryParser queryParser=null;
Query query=queryParser.parse(queryString);
//2、进行查询
IndexSearcher indexSearcher=null;
Filter filter=null;
//得到的topDocs总结果数
TopDocs topDocs= indexSearcher.search(query,filter,10000);
//3、打印结果 scoreDoc 放的文档编号
for( ScoreDoc scoreDoc: topDocs.scoreDocs){
int docSn=scoreDoc.doc;//文档内部编号
Document doc= indexSearcher.doc(docSh);//根据文档编号取出相应文档
//获取name属性的值
doc.get("name");
}
3、工具类
File2DocumentUtils
//文件 filename content path size
public static Document fileDocument(String path){
File file=new File(path);
Document doc=new Document();
doc.add(new Field("name",file.getName(),Store.YES{是否存储 枚举},Index.ANALYZED{是否索引}));
doc.add(new Field("content",readFileContent(file),Store.YES{是否存储 枚举},Index.ANALYZED{是否索引}));
doc.add(new Field("size",String.valueof(file.length()),Store.YES{是否存储 枚举},Index.ANALYZED{是否索引}));
doc.add(new Field("path",file.getAbsolutePath(),Store.YES{是否存储 枚举},Index.ANALYZED{是否索引}));
return doc;
}
//读取文件内容
public static String readFileContent(File file){
BufferedReader reader=new BufferedEeader(new InputStreamReader(new FileInputStream(file)));
StringBuffer content=new StringBuffer();
for(String line=null;(line=reader.readLine())!=null;){
content.append(line).append("\n");
return content.toString();
是否索引 ---> 进行索引----> {分词后索引、直接索引(把整个值当成一个关键词,不分词直接索引)}
7、索引库的位置
1、建立索引
public void test1()throws Exception{
//Directory dir=FSDirectory.getDirectory(indexpath);//放到磁盘中
Directory dir=new RAMDDirectory();//放到内存中
Document doc=File2DocumentUtils.file2Document(filepath);
IndexWriter indexwriter=new IndexWriter(dir,analyzer,new MaxFieldLength(10000){MaxFieldLength.LLMITED 整形的最大值});//没有true可以创建和使用已经存在的索引
}
public void test2(){
Directory fsDir=FSDirectory.getDirectory(indexpath);
//1、启动时读取
Directory ramDir=new RAMDirectory();
//运行程序时操作 ramDir
IndexWriter ramIndexWriter =new IndexWriter(ramDir,analyzer,MaxFieldLength.LIMITED);
//添加Document
Document doc=File2DocumentUtils.file2Document(filepath);
ramIndexWriter.addDocument(doc);
ramIndexWriter.close();//一定要关闭在存储,因为有缓存,不关闭会导致索引丢失
//2、退出程序时保存
IndexWriter fsIndexWriter =new IndexWriter(fsDir,true,analyzer,MaxFieldLength.LIMITED);
fsIndexWriter.addIndexesNoOptimis(new Directory[](ramdir));
fsIndexWriter.commit();
fsIndexWriter.optimize();//优化
fsIndexWriter.close();
}
//优化
public void test3(){
//1、启动时读取
// Directory ramDir=new RAMDirectory();
IndexWriter fsIndexWriter =new IndexWriter(ramDir,analyzer,MaxFieldLength.LIMITED);
fsIndexWriter.optimze();//优化是做合并操作
8、分词器
1、英文分词器 输入文本--》关键词切分--》去除停用词--》形态还原--》转为小写
2、中文分词 单词分词 二分法分词 词典分词 词库分词器 MMAnalyzer();
9、关键词高亮
//准备高亮器
ForMatter formatter=new SimpleHTMLFOrMatter("<font color='red'>","</font>");
Score score=new QueryScore(query);
HeighLighter highter=new HeighLighter(formatter,score);
Fragmenter fragmenter=new SimpleFragmeter("1000");//指定摘要字符
//高亮
//返回高亮后的结果,如果当前属性之中没有出现关键词,会返回null
String hc=heighlighter.getBestFragment(analyzer,“content”,doc.get("content"));
if(hc!=null){
doc.getField("content").setValue(hc);
}else{
String content=doc.get("content");
int endIndex=Math.min(50,content.length());
hc=content.subString(0,endIndex);//截取前50个字符
10、查询
1、查询字符串,可以使用查询语法
2、使用对象 Query
public class QueryTest{
IndexDao indexDao=newIndexDao();
public void test(){
Query query=null;
public void testTermQuery(String queryString,int firstResult,int maxResult){//关键词查询
Term term=new Term("name","房间");//英文关键词全是小写字符
Query query=new TermQuery(term);
QueryResult qr=indexDao.search(query,0,100);
for(Document doc:qr.getRecordList()){
File2DocumentUtils.printDocumentInfo(doc);
}
//TermQuery
//RangeQuery
//WidcardQuery
//PhraseQuery
//BooleanQuery
public QueryResult search(String queryString,int firstResult,int max Result){
try{
//1、把要搜索的文本解析成query
String[] fields={"name","content"};
QueryParser queryParser=new MultiFieldQueryParser(fields,analyzer);
Query query=queryParser.parse(queryString);
return search(query,firstResult,maxResults);
}catch(Exception e){
throw new RuntimeException(e);
}finally{
try{
}catch(IOException e){
e.printStackTrace();
//范围查询
public void testRangeQuery(){
Term lowerterm=new Term("size","200");
Term upperterm=new Term("size","500")
Query query=new RangeQuery(lowerTerm,upperTerm,true);//true包含边界
NumberTools.longToString(lowerTerm,upperTerm,true);
NumberTools
queryAndPrintResult(query);
}
//通配符查询 ? 代表一个字符 * 代表多个
public void testWidcarQuery(){
Term term=new Term("name","roo?");
Query query=new WidcarQuery(term);
queryAndPrintresult(query);
//短语查询
public void testParseQuery(){
PhraseQuery phraseQuery=new PhraseQuery();
//phraseQuery.add(new Term("name","笑话",1));//1代表位置
phraseQuery.add(new Term("name","房间"));
phraseQuery.add(new Term("name","绅士"));
phraseQuery.setSlop(5);//指定指定的词中间隔了几个词
}
//boolean 查询
public void testBooleanQuery(){
BooleanQuery boolQuery=new BooleanQuery();
booleanQuery.add(query1,Occur.MUST);//条件一必须出现
11、查询结果排序
12、过滤器