lunece全文检索的入门与简单优化

2016-12-15 项目中需要加载下面几个工具包










1
package com.cn.shupu.util; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.FileInputStream; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 8 import java.nio.file.Paths; 9 import java.util.ArrayList; 10 import java.util.Date; 11 import java.util.List; 12 13 import org.apache.lucene.analysis.Analyzer; 14 import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer; 15 import org.apache.lucene.document.Document; 16 import org.apache.lucene.document.Field.Store; 17 import org.apache.lucene.document.TextField; 18 import org.apache.lucene.index.DirectoryReader; 19 import org.apache.lucene.index.IndexWriter; 20 import org.apache.lucene.index.IndexWriterConfig; 21 import org.apache.lucene.index.LogByteSizeMergePolicy; 22 import org.apache.lucene.index.LogMergePolicy; 23 import org.apache.lucene.index.IndexWriterConfig.OpenMode; 24 import org.apache.lucene.queryparser.classic.QueryParser; 25 import org.apache.lucene.search.IndexSearcher; 26 import org.apache.lucene.search.Query; 27 import org.apache.lucene.search.ScoreDoc; 28 import org.apache.lucene.search.TopDocs; 29 import org.apache.lucene.search.highlight.Fragmenter; 30 import org.apache.lucene.search.highlight.Highlighter; 31 import org.apache.lucene.search.highlight.InvalidTokenOffsetsException; 32 import org.apache.lucene.search.highlight.QueryScorer; 33 import org.apache.lucene.search.highlight.SimpleFragmenter; 34 import org.apache.lucene.search.highlight.SimpleHTMLFormatter; 35 import org.apache.lucene.store.Directory; 36 import org.apache.lucene.store.FSDirectory; 37 import org.apache.lucene.store.RAMDirectory; 38 39 public class LuneceTest { 40 41 // 用来文件 42 public static List<File> files = new ArrayList<File>(); 43 44 // 保存索引文件 45 public static List<File> saveFile(File sourceFile) { 46 47 File[] fs = sourceFile.listFiles(); 48 49 for (int i = 0; i < fs.length; i++) { 50 51 if (fs[i].isFile()) { 52 53 files.add(fs[i]); 54 } else { 55 56 saveFile(fs[i]); 57 } 58 59 } 60 61 return files; 62 63 } 64 65 // 获取文件中的内容 66 public static String saveContent(File file) { 67 68 String content = ""; 69 70 try { 71 72 // 创建一个字符输入流 73 FileInputStream fis = new FileInputStream(file); 74 75 // 创建一个桥梁让字节流转化为字符流 76 InputStreamReader isr = new InputStreamReader(fis, "GBK"); 77 // 创建一个字符流缓存区 78 BufferedReader br = new BufferedReader(isr); 79 80 String s = null; 81 82 while ((s = br.readLine()) != null) { 83 84 // 把内容拼接起来 85 content = content + " " + s; 86 87 } 88 89 // 关闭流 90 br.close(); 91 isr.close(); 92 fis.close(); 93 94 } catch (Exception e) { 95 // TODO Auto-generated catch block 96 e.printStackTrace(); 97 } 98 99 return content; 100 101 } 102 103 // 创建索引 104 public static void createIndex(String sourcePath, String indexPath) { 105 106 // 要索引的文件路径 107 File sourceFile = new File(sourcePath); 108 109 // 获取索引文件的文件 110 List<File> fs = saveFile(sourceFile); 111 112 Date date1 = new Date(); 113 114 // 对文件进行索引 115 // 索引文件存放路径 116 Directory dir; 117 118 try { 119 120 // 索引优化 121 RAMDirectory rd = new RAMDirectory(); 122 // 这里的路径为保存索引的路径 123 dir = FSDirectory.open(Paths.get(indexPath)); 124 // 创建一个分词器 125 SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer(); 126 IndexWriterConfig iwc = new IndexWriterConfig(analyzer);// 初始化索引器 127 // 创建索引器 128 // IndexWriter writer = new IndexWriter(dir, iwc);// 129 // 第一个参数为索引存放的位置,第二参数为初始化参数 130 131 IndexWriter writer = new IndexWriter(rd, iwc); 132 133 IndexWriterConfig iwc2 = new IndexWriterConfig(analyzer);// 初始化索引器 134 iwc2.setOpenMode(OpenMode.CREATE_OR_APPEND); 135 iwc2.setMaxBufferedDocs(256); 136 iwc2.setRAMBufferSizeMB(100); 137 138 // SetMergeFactor是控制segment合并频率的,其决定了一个索引块中包括多少个文档,当硬盘上的索引块达到多少时, 139 // 将它们合并成一个较大的索引块。当MergeFactor值较大时,生成索引的速度较快。MergeFactor的默认值是10,建议在建立索引前将其设置的大一些。 140 LogMergePolicy mergePolicy = new LogByteSizeMergePolicy(); 141 mergePolicy.setMergeFactor(100); 142 iwc2.setMergePolicy(mergePolicy); 143 144 // 把缓存在 RAMDirectory 中的所有数据写入 FSDirectory 145 IndexWriter is = new IndexWriter(dir, iwc2); 146 147 for (int i = 0; i < fs.size(); i++) { 148 149 String content = ""; 150 151 // 只对.txt文件进行索引 152 // 获取文件类型 153 int a = fs.get(i).getName().lastIndexOf("."); 154 155 String fileType = fs.get(i).getName().substring(a + 1); 156 157 if ("txt".equals(fileType)) { 158 159 content = saveContent(fs.get(i)); 160 161 // System.out.println(content); 162 163 // System.out.println(fs.get(i).getName()); 164 Document doc = new Document(); 165 166 // doc.add(new TextField("filename", fs.get(i).getName(), 167 // Store.YES)); 168 doc.add(new TextField("path", fs.get(i).getAbsolutePath(), Store.YES)); 169 doc.add(new TextField("content", content, Store.YES)); 170 writer.addDocument(doc); 171 172 } 173 174 } 175 writer.commit(); 176 writer.close(); 177 // 178 is.addIndexes(new Directory[] { rd }); 179 is.forceMerge(5); 180 is.forceMerge(100); 181 is.maybeMerge(); 182 is.close(); 183 184 } catch (IOException e) { 185 // TODO Auto-generated catch block 186 e.printStackTrace(); 187 } 188 189 Date date2 = new Date(); 190 System.out.println("创建索引-----耗时:" + (date2.getTime() - date1.getTime()) + "ms "); 191 192 } 193 194 // 搜索文件 195 public static void search(String indexPath, String keyword) { 196 197 Date date1 = new Date(); 198 199 Directory dir; 200 201 try { 202 203 dir = FSDirectory.open(Paths.get(indexPath)); 204 205 // 创建分词器 206 SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer(); 207 // 打开索引的存放位置 208 DirectoryReader dr = DirectoryReader.open(dir); 209 210 // 创建检索器 211 IndexSearcher is = new IndexSearcher(dr); 212 213 QueryParser parser = new QueryParser("content", analyzer);// 第一个参数为要搜索的字段名,第二额分词器 214 215 Query query = parser.parse(keyword); 216 217 TopDocs results = is.search(query, 100); 218 219 ScoreDoc[] hits = results.scoreDocs;// 检索得到结果集 220 221 for (int i = 0; i < hits.length; i++) { 222 223 // 获取一个条记录 224 Document doc = is.doc(hits[i].doc); 225 226 // 获取路径 227 String path = doc.get("path"); 228 // 获取 内容 229 String content = doc.get("content"); 230 String filename = doc.get("filename"); 231 232 String s = hight(query, analyzer, "content", content, 200); 233 234 System.out.println("____________________________"); 235 236 // System.out.println("文件名--------" + filename); 237 // 238 // sSystem.out.println("内容:---------" + s); 239 240 System.out.println("文件路径-----" + path); 241 242 System.out.println("____________________________"); 243 244 } 245 246 dr.close(); 247 dir.close(); 248 249 } catch (Exception e) { 250 // TODO Auto-generated catch block 251 e.printStackTrace(); 252 } 253 254 Date date2 = new Date(); 255 System.out.println("查看索引-----耗时:" + (date2.getTime() - date1.getTime()) + "ms "); 256 257 } 258 259 260 /** 261 * 获取高亮显示结果的html代码 262 * 263 * @param query 264 * 查询 265 * @param analyzer 266 * 分词器 267 * @param fieldName 268 * 域名 269 * @param fieldContent 270 * 域内容 271 * @param fragmentSize 272 * 结果的长度(不含html标签长度) 273 * @return 结果(一段html代码) 274 * @throws IOException 275 * @throws InvalidTokenOffsetsException 276 */ 277 public static String hight(Query query, Analyzer analyzer, String filedname, String filedContent, int fragmentSize) 278 throws IOException, InvalidTokenOffsetsException { 279 280 // 创建一个高亮器 281 Highlighter hightlighter = new Highlighter(new SimpleHTMLFormatter("<font color='red'>", "</font>"), 282 new QueryScorer(query)); 283 284 // 查询结果的内容长度设定 285 Fragmenter framenter = new SimpleFragmenter(fragmentSize); 286 287 hightlighter.setTextFragmenter(framenter); 288 289 return hightlighter.getBestFragment(analyzer, filedname, filedContent); 290 } 291 292 public static void main(String[] args) { 293 294 createIndex("D:\图书文件", "c:\expal"); 295 296 search("c:\expal", "炎");// 22385ms 10380ms 35221ms 96583ms 66798ms 297 // 169438ms 179478ms 298 299 }
原文地址:https://www.cnblogs.com/git-niu/p/6183257.html