由于各种原因大概很长时间都要折腾solr了,既来之则安之,花了好多精力折腾的项目怎么能不好好整理学习一下,深入理解一下solr的原理。目前接触到的搜索相关的几乎就是solr和elasticsearch平分天下,而这两者由都是基于luncene开发的全文检索系统,elasticsearch暂时还没有接触,暂时被solr虐的死去活来。
什么是luncene? Luncene是java开发的信息检索类库,专注于文本的搜索和索引,对文本中提取出来的数据进行索引和检索,也就是说luncene提供了全文检索的两个核心功能,索引和检索,而其他的则需要用户自己实现,如solr和elasticsearch就是各自基于luncene的实现。
Luncene的索引是什么? Lunecen的索引本质上是一种倒排索引,倒排索引的功能是快速的返回要查找的单词包含在哪些文档中。
luncene的索引过程?索引的基本单位是文档,一个文档可以包含多个域,域值可以被索引也可以被单独存值,Luncene的索引过程就是从原始的文本中提取数据,并创建对应的document实例,一个document中包含了多个域,域是用来保存原始数据,然后分析过程将域处理成语汇单元添加到段文件中,核心过程可以总结成为,提取文档,分析文档,添加文档三个过程。提取文档过程,从各种文本中提取数据,对应的程序指的就是封装document的过程,分析文档,将要索引的数据封装成一个个的document对象之后会交给luncene来分析,分析过程会将数据分割成一个个的语汇单元,并做一些处理,比如对数据进行大小写转换,去除一些停词,无意义的词,最后生成语汇单元,最后对生成语汇单元写入到索引文件中。
来写一个对本地文件夹所有文件建索引的程序,对F盘下的所有文件的文件名建索引,生成的索引存放在F:\\Lucence\\Fdiskindex 目录下
添加pom依赖
<lucene.version>4.6.1</lucene.version> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>${lucene.version}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-common</artifactId> <version>${lucene.version}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-queryparser</artifactId> <version>${lucene.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-highlighter --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-highlighter</artifactId> <version>${lucene.version}</version> </dependency>
f盘文件建索引
public class DiskIndex { private static Logger logger = Logger.getLogger(DiskIndex.class); private String IndexOutputStr; private String indexRootPath; public String getIndexOutputStr() { return IndexOutputStr; } public void setIndexOutputStr(String indexOutputStr) { IndexOutputStr = indexOutputStr; } public String getIndexRootPath() { return indexRootPath; } public void setIndexRootPath(String indexRootPath) { this.indexRootPath = indexRootPath; } private IndexWriter iwriter; public void index() { Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_46); IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_46, analyzer); try { Directory directory = FSDirectory.open(new File(IndexOutputStr)); iwriter = new IndexWriter(directory, config); File inputfile = new File(indexRootPath); File[] files = inputfile.listFiles(); for (File file : files) { if(fileFilter(file)) { addDoc(file); } } } catch (IOException e) { e.printStackTrace(); logger.warn("打开文件异常"); } } private void addDoc(File file) { if (file.isDirectory()&&(!file.getPath().contains("RECYCLE.BIN"))) { try{ File[] filelist = file.listFiles(); for ( File afile: filelist ) { addDoc(afile); } }catch (Exception E){ } } else if (file.isFile()&&(!file.getPath().contains("RECYCLE.BIN"))) { try { indexFile(file); } catch (IOException e) { logger.info("索引文件出错 path = " + file.getPath()); } } } private void close() throws IOException { iwriter.close(); } private void indexFile(File file) throws IOException { logger.info(" index file = "+ file.getPath()); String fileName = file.getName(); String filePath = file.getPath(); Long fileSize = file.length(); Document doc = new Document(); doc.add(new Field("filename", fileName, TextField.TYPE_STORED)); doc.add(new Field("filepath", filePath, TextField.TYPE_STORED)); doc.add(new LongField("fileSize", fileSize, LongField.TYPE_STORED)); iwriter.addDocument(doc); } public static boolean fileFilter(File file){ Boolean flag = true; if(file.getPath().contains("spark")){ flag = false; } if(file.getPath().contains("hive")){ flag = false; } return flag; } public static void main(String[] args) throws IOException { DiskIndex index = new DiskIndex(); index.setIndexRootPath("F:\\"); index.setIndexOutputStr("F:\\Lucence\\Fdiskindex"); index.index(); index.close(); } }
再来一个搜索程序,搜索F盘下和redis有关的文件
public class DiskSearch { private Logger logger = Logger.getLogger(DiskIndex.class); private DirectoryReader ireader = null; private IndexSearcher isearcher = null; private String indexdir = "F:\\Lucence\\Fdiskindex"; public void search(String queryField) { Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_46); QueryParser parser = new QueryParser(Version.LUCENE_46, "filename", analyzer); Directory directory = null; try { directory = FSDirectory.open(new File(indexdir)); DirectoryReader ireader = DirectoryReader.open(directory); IndexSearcher isearcher = new IndexSearcher(ireader); Query query = parser.parse(queryField);//query word ScoreDoc[] hits = isearcher.search(query, null, 1000).scoreDocs; for (int i = 0; i < hits.length; i++) { Document hitDoc = isearcher.doc(hits[i].doc); System.out.println("____________________________"); System.out.println(hitDoc.get("filename")); System.out.println(hitDoc.get("filepath")); } ireader.close(); directory.close(); } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } } public static void main(String[] args) { DiskSearch search = new DiskSearch(); search.search("redis"); } }
查看返回结果