欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Lucene 全文检索

程序员文章站 2022-07-01 09:54:08
...
[b]1,信息检索与数据库的搜索对比 -- DB就不是为全文检索而设计的[/b]
a> 数据库的搜索不能实现我们的全文检索的要求,原因如下: 匹配效果:如搜索 ant,在 sql 中使用 like %ant%'是会搜索出 planting 的,但他不应出现.
b> 查出的结果没有相关度排序,不知道有用的结果在哪一页.
c> 搜索速度太慢,达不到毫秒级的要求

[b]2, 整体流程[/b]
[img]http://dl.iteye.com/upload/attachment/476858/6ab1048a-1920-3157-a2a6-46d453785787.jpg[/img]


[img]http://dl.iteye.com/upload/attachment/476870/080a8328-0ed7-3ef9-b462-86722279bc25.jpg[/img]


[b]3, 主要概念[/b]
索引, 分词器, 高亮器, 过滤器

[b]4, 代码[/b]
package cn.itcast.lucene.helloworld;

import jeasy.analysis.MMAnalyzer;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.junit.Test;

import cn.itcast.lucene.utils.File2DocumentUtils;

public class HelloWorld2 {

String filePath = "luceneDatasource\\ch1.txt";
String filePath2 = "luceneDatasource\\ch2.txt";
String filePath3 = "luceneDatasource\\ch3.txt";
String filePath4 = "luceneDatasource\\ch4.txt";

String indexPath = "luceneIndex2";

Analyzer analyzer = new MMAnalyzer();

/**
* 创建索引
*
* IndexWriter 是用来操作(增、删、改)索引库的
*/
@Test
public void createIndex() throws Exception {
// file --> doc
Document doc = File2DocumentUtils.file2Document(filePath);
Document doc2 = File2DocumentUtils.file2Document(filePath2);
Document doc3 = File2DocumentUtils.file2Document(filePath3);
Document doc4 = File2DocumentUtils.file2Document(filePath4);

// 建立索引
IndexWriter indexWriter = new IndexWriter(indexPath, analyzer, true,
MaxFieldLength.LIMITED);
indexWriter.addDocument(doc);
indexWriter.addDocument(doc2);
indexWriter.addDocument(doc3);
indexWriter.addDocument(doc4);

indexWriter.close();
}

/**
* 搜索
*
* IndexSearcher 是用来在索引库中进行查询的
*/
@Test
public void search() throws Exception {
// String queryString = "document";
String queryString = "商品";

// 1,把要搜索的文本解析为 Query
String[] fields = { "content" };
QueryParser queryParser = new MultiFieldQueryParser(fields, analyzer);
Query query = queryParser.parse(queryString);

// 2,进行查询
IndexSearcher indexSearcher = new IndexSearcher(indexPath);
Filter filter = null;
TopDocs topDocs = indexSearcher.search(query, filter, 10000);
System.out.println("总共有【" + topDocs.totalHits + "】条匹配结果");

// 3,打印结果
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
int docSn = scoreDoc.doc; // 文档内部编号
Document doc = indexSearcher.doc(docSn); // 根据编号取出相应的文档
File2DocumentUtils.printDocumentInfo(doc); // 打印出文档信息
}
}
}

package cn.itcast.lucene.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumberTools;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;

public class File2DocumentUtils {

// 文件:name, content, size, path
public static Document file2Document(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", NumberTools.longToString(file.length()), Store.YES, Index.NOT_ANALYZED));
doc.add(new Field("path", file.getAbsolutePath(), Store.YES, Index.NOT_ANALYZED));
return doc;
}

// public static void document2File(Document doc ){
//
// }

/**
* 读取文件内容
*/
public static String readFileContent(File file) {
try {
BufferedReader reader = new BufferedReader(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();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

/**
* <pre>
* 获取 name 属性的值的两种方法:
* 1,Field f = doc.getField("name");
* f.stringValue();
* 2,doc.get("name");
* </pre>
*
* @param doc
*/
public static void printDocumentInfo(Document doc) {
// Field f = doc.getField("name");
// f.stringValue();
System.out.println("------------------------------");
System.out.println("name = " + doc.get("name"));
System.out.println("content = " + doc.get("content"));
System.out.println("size = " + NumberTools.stringToLong(doc.get("size")));
System.out.println("path = " + doc.get("path"));
}

}



5, 相关查询文件 & JAR包
见附件