什么是lucene
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎
为什么我们要用Lucene?对比数据库
1.lucene可以对文件进行检索,这是数据库所不能的
2.对文本检索,lucene可以使用索引,检索效率高
3.lucene消耗内存少
4.lucene可以对搜索结果进行排名,进行高亮显示等。
lucene的流程
全文检索的流程分为两大部分:索引流程、搜索流程。
索引流程:采集数据—>构建文档对象—>创建索引(将文档写入索引库)。
搜索流程:创建查询—>执行搜索—>渲染搜索结果。
代码演示
基于lucene7.7
索引流程:
public class Index {
// 写索引实例
private IndexWriter writer;
public Index() throws Exception {
// 得到索引所在目录的路径,一般都用FSDirectory会根据环境选择最好的打开方式
Directory directory = FSDirectory.open(Paths.get("/Users/temp/lucene/index"));
// 保存用于创建IndexWriter的所有配置。会使用默认分词器
StandardAnalyzer standardAnalyzer = new StandardAnalyzer();
CharArraySet stopwordSet = standardAnalyzer.getStopwordSet();
CharArraySet charArraySet = new CharArraySet(stopwordSet, true);
boolean g32 = charArraySet.add("g32");
System.out.println(g32);
System.out.println(charArraySet);
IndexWriterConfig iwConfig = new IndexWriterConfig(new StandardAnalyzer(charArraySet));
// 实例化IndexWriter
writer = new IndexWriter(directory, iwConfig);
}
public static void main(String[] args) throws Exception {
//被索引数据的路径
String dataDir = "/Users/temp/lucene/data";
Index indexer = null;
int numIndexed = 0;
//索引开始时间
long start = System.currentTimeMillis();
try {
indexer = new Index();
indexer.deleteAll();
numIndexed = indexer.index(dataDir);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
indexer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//索引结束时间
long end = System.currentTimeMillis();
System.out.println("索引:" + numIndexed + " 个文件 花费了" + (end - start) + " 毫秒");
}
public long deleteAll() throws IOException {
return writer.deleteAll();
}
public void close() throws IOException {
writer.close();
}
private static Document getDocument(File f) throws Exception {
Document doc = new Document();
//把设置好的索引加到Document里,以便在确定被索引文档
doc.add(new TextField("contents", new FileReader(f)));
//Field.Store.YES:在查找结果时可以还原文档,为NO不能还原文档
doc.add(new TextField("fileName", f.getName(), Field.Store.YES));
//把完整路径存在索引文件里
doc.add(new TextField("fullPath", f.getCanonicalPath(), Field.Store.YES));
return doc;
}
public int index(String dataDir) throws Exception {
File[] files = new File(dataDir).listFiles();
for (File file : files) {
//索引指定文件
indexFile(file);
}
//返回索引了多少个文件
return writer.getDocStats().numDocs;
}
public void indexFile(File f) throws Exception {
//输出索引文件的路径
System.out.println("索引文件:" + f.getCanonicalPath());
//获取文档,文档里再设置每个字段
Document doc = getDocument(f);
//开始写入,就是把文档写进了索引文件里去了;
writer.addDocument(doc);
}
}
搜索流程:
public class Search {
public static void search(String indexDir, String q) throws Exception {
// 得到读取索引文件的路径
Directory dir = FSDirectory.open(Paths.get(indexDir));
// 通过dir得到的路径下的所有的文件
IndexReader reader = DirectoryReader.open(dir);
// 建立索引查询器
IndexSearcher is = new IndexSearcher(reader);
// 实例化分析器
Analyzer analyzer = new StandardAnalyzer();
// 建立查询解析器
/**
* 第一个参数是要查询的字段; 第二个参数是分析器Analyzer
*/
QueryParser parser = new QueryParser("contents", analyzer);
// 根据传进来的p查找
Query query = parser.parse(q);
// 计算索引开始时间
long start = System.currentTimeMillis();
// 开始查询
/**
* 第一个参数是通过传过来的参数来查找得到的query; 第二个参数是要出查询的行数
*/
TopDocs hits = is.search(query, 10);
// 计算索引结束时间
long end = System.currentTimeMillis();
System.out.println("匹配 " + q + " ,总共花费" + (end - start) + "毫秒" + "查询到" + hits.totalHits + "个记录");
// 遍历hits.scoreDocs,得到scoreDoc
/**
* ScoreDoc:得分文档,即得到文档 scoreDocs:代表的是topDocs这个文档数组
*
* @throws Exception
*/
for (ScoreDoc scoreDoc : hits.scoreDocs) {
Document doc = is.doc(scoreDoc.doc);
System.out.println(doc.get("fullPath"));
System.out.println(doc.get("fileName"));
}
// 关闭reader
reader.close();
}
public static void main(String[] args) {
String indexDir = "/Users/temp/lucene/index";
//我们要搜索的内容
String q = "i love you";
try {
search(indexDir, q);
} catch (Exception e) {
e.printStackTrace();
}
}
}
其他
上面代码的lucene,只是一个基础的例子。很多其他的全文检索工具都是基于lucene在做,比如solr,elasticsearch等。
其他参考
https://mp.weixin.qq.com/s/nhyb9ZwQRJjcRDXVFK0_1w
欢迎关注公众号蜜蜂技术巢了解更多知识