分享

Lucene5学习之LuceneUtils工具类简单封装

 Bladexu的文库 2017-09-22

花了整整一天时间,将Lucene5中有关索引的常见操作进行了简单封装,废话不多说,上代码:

  1. package com.yida.framework.lucene5.util;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.concurrent.ExecutorService;  
  5. import java.util.concurrent.locks.Lock;  
  6. import java.util.concurrent.locks.ReentrantLock;  
  7.   
  8. import org.apache.lucene.index.DirectoryReader;  
  9. import org.apache.lucene.index.IndexReader;  
  10. import org.apache.lucene.index.IndexWriter;  
  11. import org.apache.lucene.index.IndexWriterConfig;  
  12. import org.apache.lucene.search.IndexSearcher;  
  13. import org.apache.lucene.store.Directory;  
  14. import org.apache.lucene.store.LockObtainFailedException;  
  15. /** 
  16.  * Lucene索引读写器/查询器单例获取工具类 
  17.  * @author Lanxiaowei 
  18.  * 
  19.  */  
  20. public class LuceneManager {  
  21.   private volatile static LuceneManager singleton;  
  22.     
  23.   private volatile static IndexWriter writer;  
  24.     
  25.   private volatile static IndexReader reader;  
  26.     
  27.   private volatile static IndexSearcher searcher;  
  28.     
  29.   private final Lock writerLock = new ReentrantLock();  
  30.     
  31.   //private final Lock readerLock = new ReentrantLock();  
  32.     
  33.   //private final Lock searcherLock = new ReentrantLock();  
  34.   
  35.   private LuceneManager() {}  
  36.   
  37.   public static LuceneManager getInstance() {  
  38.     if (null == singleton) {  
  39.       synchronized (LuceneManager.class) {  
  40.         if (null == singleton) {  
  41.           singleton = new LuceneManager();  
  42.         }  
  43.       }  
  44.     }  
  45.     return singleton;  
  46.   }  
  47.   
  48.   /** 
  49.    * 获取IndexWriter单例对象 
  50.    * @param dir 
  51.    * @param config 
  52.    * @return 
  53.    */  
  54.   public IndexWriter getIndexWriter(Directory dir, IndexWriterConfig config) {  
  55.     if(null == dir) {  
  56.       throw new IllegalArgumentException("Directory can not be null.");  
  57.     }  
  58.     if(null == config) {  
  59.       throw new IllegalArgumentException("IndexWriterConfig can not be null.");  
  60.     }  
  61.     try {  
  62.       writerLock.lock();  
  63.       if(null == writer){  
  64.         //如果索引目录被锁,则直接抛异常  
  65.         if(IndexWriter.isLocked(dir)) {  
  66.           throw new LockObtainFailedException("Directory of index had been locked.");  
  67.         }  
  68.         writer = new IndexWriter(dir, config);  
  69.       }  
  70.     } catch (LockObtainFailedException e) {  
  71.       e.printStackTrace();  
  72.     } catch (IOException e) {  
  73.       e.printStackTrace();  
  74.     } finally {  
  75.       writerLock.unlock();  
  76.     }  
  77.     return writer;  
  78.   }  
  79.     
  80.   /** 
  81.    * 获取IndexReader对象 
  82.    * @param dir 
  83.    * @param enableNRTReader  是否开启NRTReader 
  84.    * @return 
  85.    */  
  86.   public IndexReader getIndexReader(Directory dir,boolean enableNRTReader) {  
  87.     if(null == dir) {  
  88.       throw new IllegalArgumentException("Directory can not be null.");  
  89.     }  
  90.     try {  
  91.       if(null == reader){  
  92.         reader = DirectoryReader.open(dir);  
  93.       } else {  
  94.         if(enableNRTReader && reader instanceof DirectoryReader) {  
  95.           //开启近实时Reader,能立即看到动态添加/删除的索引变化  
  96.           reader = DirectoryReader.openIfChanged((DirectoryReader)reader);  
  97.         }  
  98.       }  
  99.     } catch (IOException e) {  
  100.       e.printStackTrace();  
  101.     }  
  102.     return reader;  
  103.   }  
  104.     
  105.   /** 
  106.    * 获取IndexReader对象(默认不启用NETReader) 
  107.    * @param dir 
  108.    * @return 
  109.    */  
  110.   public IndexReader getIndexReader(Directory dir) {  
  111.     return getIndexReader(dir, false);  
  112.   }  
  113.     
  114.   /** 
  115.    * 获取IndexSearcher对象 
  116.    * @param reader    IndexReader对象实例 
  117.    * @param executor  如果你需要开启多线程查询,请提供ExecutorService对象参数 
  118.    * @return 
  119.    */  
  120.   public IndexSearcher getIndexSearcher(IndexReader reader,ExecutorService executor) {  
  121.     if(null == reader) {  
  122.       throw new IllegalArgumentException("The indexReader can not be null.");  
  123.     }  
  124.     if(null == searcher){  
  125.       searcher = new IndexSearcher(reader);  
  126.     }  
  127.     return searcher;  
  128.   }  
  129.     
  130.   /** 
  131.    * 获取IndexSearcher对象(不支持多线程查询) 
  132.    * @param reader    IndexReader对象实例 
  133.    * @return 
  134.    */  
  135.   public IndexSearcher getIndexSearcher(IndexReader reader) {  
  136.     return getIndexSearcher(reader, null);  
  137.   }  
  138. }  
  139. package com.yida.framework.lucene5.util;  
  140.   
  141. import java.io.IOException;  
  142. import java.nio.file.Paths;  
  143. import java.util.ArrayList;  
  144. import java.util.Collections;  
  145. import java.util.List;  
  146. import java.util.Set;  
  147. import java.util.concurrent.ExecutorService;  
  148.   
  149. import org.ansj.lucene5.AnsjAnalyzer;  
  150. import org.apache.lucene.analysis.Analyzer;  
  151. import org.apache.lucene.document.Document;  
  152. import org.apache.lucene.document.Field;  
  153. import org.apache.lucene.document.TextField;  
  154. import org.apache.lucene.index.IndexReader;  
  155. import org.apache.lucene.index.IndexWriter;  
  156. import org.apache.lucene.index.IndexWriterConfig;  
  157. import org.apache.lucene.index.IndexableField;  
  158. import org.apache.lucene.index.Term;  
  159. import org.apache.lucene.queryparser.classic.QueryParser;  
  160. import org.apache.lucene.search.IndexSearcher;  
  161. import org.apache.lucene.search.Query;  
  162. import org.apache.lucene.search.ScoreDoc;  
  163. import org.apache.lucene.search.TopDocs;  
  164. import org.apache.lucene.search.highlight.Formatter;  
  165. import org.apache.lucene.search.highlight.Fragmenter;  
  166. import org.apache.lucene.search.highlight.Highlighter;  
  167. import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;  
  168. import org.apache.lucene.search.highlight.QueryScorer;  
  169. import org.apache.lucene.search.highlight.Scorer;  
  170. import org.apache.lucene.search.highlight.SimpleFragmenter;  
  171. import org.apache.lucene.search.highlight.SimpleHTMLFormatter;  
  172. import org.apache.lucene.store.Directory;  
  173. import org.apache.lucene.store.FSDirectory;  
  174.   
  175. /** 
  176.  * Lucene工具类(基于Lucene5.0封装) 
  177.  * @author Lanxiaowei 
  178.  * 
  179.  */  
  180. public class LuceneUtils {  
  181.   private static final LuceneManager luceneManager = LuceneManager.getInstance();  
  182.   private static Analyzer analyzer = new AnsjAnalyzer();  
  183.     
  184.   /** 
  185.    * 打开索引目录 
  186.    *  
  187.    * @param luceneDir 
  188.    * @return 
  189.    * @throws IOException 
  190.    */  
  191.   public static FSDirectory openFSDirectory(String luceneDir) {  
  192.     FSDirectory directory = null;  
  193.     try {  
  194.       directory = FSDirectory.open(Paths.get(luceneDir));  
  195.       /** 
  196.        * 注意:isLocked方法内部会试图去获取Lock,如果获取到Lock,会关闭它,否则return false表示索引目录没有被锁, 
  197.        * 这也就是为什么unlock方法被从IndexWriter类中移除的原因 
  198.        */  
  199.       IndexWriter.isLocked(directory);  
  200.     } catch (IOException e) {  
  201.       e.printStackTrace();  
  202.     }  
  203.     return directory;  
  204.   }  
  205.     
  206.   /** 
  207.    * 关闭索引目录并销毁 
  208.    * @param directory 
  209.    * @throws IOException 
  210.    */  
  211.   public static void closeDirectory(Directory directory) throws IOException {  
  212.     if (null != directory) {  
  213.       directory.close();  
  214.       directory = null;  
  215.     }  
  216.   }  
  217.     
  218.   /** 
  219.    * 获取IndexWriter 
  220.    * @param dir 
  221.    * @param config 
  222.    * @return 
  223.    */  
  224.   public static IndexWriter getIndexWrtier(Directory dir, IndexWriterConfig config) {  
  225.     return luceneManager.getIndexWriter(dir, config);  
  226.   }  
  227.     
  228.   /** 
  229.    * 获取IndexWriter 
  230.    * @param dir 
  231.    * @param config 
  232.    * @return 
  233.    */  
  234.   public static IndexWriter getIndexWrtier(String directoryPath, IndexWriterConfig config) {  
  235.     FSDirectory directory = openFSDirectory(directoryPath);  
  236.     return luceneManager.getIndexWriter(directory, config);  
  237.   }  
  238.     
  239.   /** 
  240.    * 获取IndexReader 
  241.    * @param dir 
  242.    * @param enableNRTReader  是否开启NRTReader 
  243.    * @return 
  244.    */  
  245.   public static IndexReader getIndexReader(Directory dir,boolean enableNRTReader) {  
  246.     return luceneManager.getIndexReader(dir, enableNRTReader);  
  247.   }  
  248.     
  249.   /** 
  250.    * 获取IndexReader(默认不启用NRTReader) 
  251.    * @param dir 
  252.    * @return 
  253.    */  
  254.   public static IndexReader getIndexReader(Directory dir) {  
  255.     return luceneManager.getIndexReader(dir);  
  256.   }  
  257.     
  258.   /** 
  259.    * 获取IndexSearcher 
  260.    * @param reader    IndexReader对象 
  261.    * @param executor  如果你需要开启多线程查询,请提供ExecutorService对象参数 
  262.    * @return 
  263.    */  
  264.   public static IndexSearcher getIndexSearcher(IndexReader reader,ExecutorService executor) {  
  265.     return luceneManager.getIndexSearcher(reader, executor);  
  266.   }  
  267.     
  268.   /** 
  269.    * 获取IndexSearcher(不支持多线程查询) 
  270.    * @param reader    IndexReader对象 
  271.    * @return 
  272.    */  
  273.   public static IndexSearcher getIndexSearcher(IndexReader reader) {  
  274.     return luceneManager.getIndexSearcher(reader);  
  275.   }  
  276.     
  277.   /** 
  278.    * 创建QueryParser对象 
  279.    * @param field 
  280.    * @param analyzer 
  281.    * @return 
  282.    */  
  283.   public static QueryParser createQueryParser(String field, Analyzer analyzer) {  
  284.     return new QueryParser(field, analyzer);  
  285.   }  
  286.     
  287.   /** 
  288.    * 关闭IndexReader 
  289.    * @param reader 
  290.    */  
  291.   public static void closeIndexReader(IndexReader reader) {  
  292.     if (null != reader) {  
  293.       try {  
  294.         reader.close();  
  295.         reader = null;  
  296.       } catch (IOException e) {  
  297.         e.printStackTrace();  
  298.       }  
  299.     }  
  300.   }  
  301.     
  302.   /** 
  303.    * 关闭IndexWriter 
  304.    * @param writer 
  305.    */  
  306.   public static void closeIndexWriter(IndexWriter writer) {  
  307.     if(null != writer) {  
  308.       try {  
  309.         writer.close();  
  310.         writer = null;  
  311.       } catch (IOException e) {  
  312.         e.printStackTrace();  
  313.       }  
  314.     }  
  315.   }  
  316.     
  317.   /** 
  318.    * 关闭IndexReader和IndexWriter 
  319.    * @param reader 
  320.    * @param writer 
  321.    */  
  322.   public static void closeAll(IndexReader reader, IndexWriter writer) {  
  323.     closeIndexReader(reader);  
  324.     closeIndexWriter(writer);  
  325.   }  
  326.     
  327.   /** 
  328.    * 删除索引[注意:请自己关闭IndexWriter对象] 
  329.    * @param writer 
  330.    * @param field 
  331.    * @param value 
  332.    */  
  333.   public static void deleteIndex(IndexWriter writer, String field, String value) {  
  334.     try {  
  335.       writer.deleteDocuments(new Term[] {new Term(field,value)});  
  336.     } catch (IOException e) {  
  337.       e.printStackTrace();  
  338.     }  
  339.   }  
  340.     
  341.   /** 
  342.    * 删除索引[注意:请自己关闭IndexWriter对象] 
  343.    * @param writer 
  344.    * @param query 
  345.    */  
  346.   public static void deleteIndex(IndexWriter writer, Query query) {  
  347.     try {  
  348.       writer.deleteDocuments(query);  
  349.     } catch (IOException e) {  
  350.       e.printStackTrace();  
  351.     }  
  352.   }  
  353.     
  354.   /** 
  355.    * 批量删除索引[注意:请自己关闭IndexWriter对象] 
  356.    * @param writer 
  357.    * @param terms 
  358.    */  
  359.   public static void deleteIndexs(IndexWriter writer,Term[] terms) {  
  360.     try {  
  361.       writer.deleteDocuments(terms);  
  362.     } catch (IOException e) {  
  363.       e.printStackTrace();  
  364.     }  
  365.   }  
  366.     
  367.   /** 
  368.    * 批量删除索引[注意:请自己关闭IndexWriter对象] 
  369.    * @param writer 
  370.    * @param querys 
  371.    */  
  372.   public static void deleteIndexs(IndexWriter writer,Query[] querys) {  
  373.     try {  
  374.       writer.deleteDocuments(querys);  
  375.     } catch (IOException e) {  
  376.       e.printStackTrace();  
  377.     }  
  378.   }  
  379.     
  380.   /** 
  381.    * 删除所有索引文档 
  382.    * @param writer 
  383.    */  
  384.   public static void deleteAllIndex(IndexWriter writer) {  
  385.     try {  
  386.       writer.deleteAll();  
  387.     } catch (IOException e) {  
  388.       e.printStackTrace();  
  389.     }  
  390.   }  
  391.     
  392.   /** 
  393.    * 更新索引文档 
  394.    * @param writer 
  395.    * @param term 
  396.    * @param document 
  397.    */  
  398.   public static void updateIndex(IndexWriter writer,Term term,Document document) {  
  399.     try {  
  400.       writer.updateDocument(term, document);  
  401.     } catch (IOException e) {  
  402.       e.printStackTrace();  
  403.     }  
  404.   }  
  405.     
  406.   /** 
  407.    * 更新索引文档 
  408.    * @param writer 
  409.    * @param term 
  410.    * @param document 
  411.    */  
  412.   public static void updateIndex(IndexWriter writer,String field,String value,Document document) {  
  413.     updateIndex(writer, new Term(field, value), document);  
  414.   }  
  415.     
  416.   /** 
  417.    * 添加索引文档 
  418.    * @param writer 
  419.    * @param doc 
  420.    */  
  421.   public static void addIndex(IndexWriter writer, Document document) {  
  422.     updateIndex(writer, null, document);  
  423.   }  
  424.     
  425.   /** 
  426.    * 索引文档查询 
  427.    * @param searcher 
  428.    * @param query 
  429.    * @return 
  430.    */  
  431.   public static List<Document> query(IndexSearcher searcher,Query query) {  
  432.     TopDocs topDocs = null;  
  433.     try {  
  434.       topDocs = searcher.search(query, Integer.MAX_VALUE);  
  435.     } catch (IOException e) {  
  436.       e.printStackTrace();  
  437.     }  
  438.     ScoreDoc[] scores = topDocs.scoreDocs;  
  439.     int length = scores.length;  
  440.     if (length <= 0) {  
  441.       return Collections.emptyList();  
  442.     }  
  443.     List<Document> docList = new ArrayList<Document>();  
  444.     try {  
  445.       for (int i = 0; i < length; i++) {  
  446.         Document doc = searcher.doc(scores[i].doc);  
  447.         docList.add(doc);  
  448.       }  
  449.     } catch (IOException e) {  
  450.       e.printStackTrace();  
  451.     }  
  452.     return docList;  
  453.   }  
  454.     
  455.   /** 
  456.    * 返回索引文档的总数[注意:请自己手动关闭IndexReader] 
  457.    * @param reader 
  458.    * @return 
  459.    */  
  460.   public static int getIndexTotalCount(IndexReader reader) {  
  461.     return reader.numDocs();  
  462.   }  
  463.     
  464.   /** 
  465.    * 返回索引文档中最大文档ID[注意:请自己手动关闭IndexReader] 
  466.    * @param reader 
  467.    * @return 
  468.    */  
  469.   public static int getMaxDocId(IndexReader reader) {  
  470.     return reader.maxDoc();  
  471.   }  
  472.     
  473.   /** 
  474.    * 返回已经删除尚未提交的文档总数[注意:请自己手动关闭IndexReader] 
  475.    * @param reader 
  476.    * @return 
  477.    */  
  478.   public static int getDeletedDocNum(IndexReader reader) {  
  479.     return getMaxDocId(reader) - getIndexTotalCount(reader);  
  480.   }  
  481.     
  482.   /** 
  483.    * 根据docId查询索引文档 
  484.    * @param reader         IndexReader对象 
  485.    * @param docID          documentId 
  486.    * @param fieldsToLoad   需要返回的field 
  487.    * @return 
  488.    */  
  489.   public static Document findDocumentByDocId(IndexReader reader,int docID, Set<String> fieldsToLoad) {  
  490.     try {  
  491.       return reader.document(docID, fieldsToLoad);  
  492.     } catch (IOException e) {  
  493.       return null;  
  494.     }  
  495.   }  
  496.     
  497.   /** 
  498.    * 根据docId查询索引文档 
  499.    * @param reader         IndexReader对象 
  500.    * @param docID          documentId 
  501.    * @return 
  502.    */  
  503.   public static Document findDocumentByDocId(IndexReader reader,int docID) {  
  504.     return findDocumentByDocId(reader, docID, null);  
  505.   }  
  506.     
  507.   /** 
  508.    * @Title: createHighlighter 
  509.    * @Description: 创建高亮器 
  510.    * @param query             索引查询对象 
  511.    * @param prefix            高亮前缀字符串 
  512.    * @param stuffix           高亮后缀字符串 
  513.    * @param fragmenterLength  摘要最大长度 
  514.    * @return 
  515.    */  
  516.   public static Highlighter createHighlighter(Query query, String prefix, String stuffix, int fragmenterLength) {  
  517.     Formatter formatter = new SimpleHTMLFormatter((prefix == null || prefix.trim().length() == 0) ?   
  518.       "<font color=\"red\">" : prefix, (stuffix == null || stuffix.trim().length() == 0)?"</font>" : stuffix);  
  519.     Scorer fragmentScorer = new QueryScorer(query);  
  520.     Highlighter highlighter = new Highlighter(formatter, fragmentScorer);  
  521.     Fragmenter fragmenter = new SimpleFragmenter(fragmenterLength <= 0 ? 50 : fragmenterLength);  
  522.     highlighter.setTextFragmenter(fragmenter);  
  523.     return highlighter;  
  524.   }  
  525.     
  526.   /** 
  527.    * @Title: highlight 
  528.    * @Description: 生成高亮文本 
  529.    * @param document          索引文档对象 
  530.    * @param highlighter       高亮器 
  531.    * @param analyzer          索引分词器 
  532.    * @param field             高亮字段 
  533.    * @return 
  534.    * @throws IOException 
  535.    * @throws InvalidTokenOffsetsException 
  536.    */  
  537.   public static String highlight(Document document,Highlighter highlighter,Analyzer analyzer,String field) throws IOException {  
  538.     List<IndexableField> list = document.getFields();  
  539.     for (IndexableField fieldable : list) {  
  540.       String fieldValue = fieldable.stringValue();  
  541.       if(fieldable.name().equals(field)) {  
  542.         try {  
  543.           fieldValue = highlighter.getBestFragment(analyzer, field, fieldValue);  
  544.         } catch (InvalidTokenOffsetsException e) {  
  545.           fieldValue = fieldable.stringValue();  
  546.         }  
  547.         return (fieldValue == null || fieldValue.trim().length() == 0)? fieldable.stringValue() : fieldValue;  
  548.       }  
  549.     }  
  550.     return null;  
  551.   }  
  552.     
  553.   /** 
  554.    * @Title: searchTotalRecord 
  555.    * @Description: 获取符合条件的总记录数 
  556.    * @param query 
  557.    * @return 
  558.    * @throws IOException 
  559.    */  
  560.   public static int searchTotalRecord(IndexSearcher search,Query query) {  
  561.     ScoreDoc[] docs = null;  
  562.     try {  
  563.       TopDocs topDocs = search.search(query, Integer.MAX_VALUE);  
  564.       if(topDocs == null || topDocs.scoreDocs == null || topDocs.scoreDocs.length == 0) {  
  565.         return 0;  
  566.       }  
  567.       docs = topDocs.scoreDocs;  
  568.     } catch (IOException e) {  
  569.       e.printStackTrace();  
  570.     }  
  571.     return docs.length;  
  572.   }  
  573.     
  574.   /** 
  575.    * @Title: pageQuery 
  576.    * @Description: Lucene分页查询 
  577.    * @param searcher 
  578.    * @param query 
  579.    * @param page 
  580.    * @throws IOException 
  581.    */  
  582.   public static void pageQuery(IndexSearcher searcher,Directory directory,Query query,Page<Document> page) {  
  583.     int totalRecord = searchTotalRecord(searcher,query);  
  584.     //设置总记录数  
  585.     page.setTotalRecord(totalRecord);  
  586.     TopDocs topDocs = null;  
  587.     try {  
  588.       topDocs = searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize());  
  589.     } catch (IOException e) {  
  590.       e.printStackTrace();  
  591.     }  
  592.     List<Document> docList = new ArrayList<Document>();  
  593.     ScoreDoc[] docs = topDocs.scoreDocs;  
  594.     int index = 0;  
  595.     for (ScoreDoc scoreDoc : docs) {  
  596.       int docID = scoreDoc.doc;  
  597.       Document document = null;  
  598.       try {  
  599.         document = searcher.doc(docID);  
  600.       } catch (IOException e) {  
  601.         e.printStackTrace();  
  602.       }  
  603.       if(index == docs.length - 1) {  
  604.         page.setAfterDoc(scoreDoc);  
  605.         page.setAfterDocId(docID);  
  606.       }  
  607.       docList.add(document);  
  608.       index++;  
  609.     }  
  610.     page.setItems(docList);  
  611.     closeIndexReader(searcher.getIndexReader());  
  612.   }  
  613.     
  614.   /** 
  615.    * @Title: pageQuery 
  616.    * @Description: 分页查询[如果设置了高亮,则会更新索引文档] 
  617.    * @param searcher 
  618.    * @param directory 
  619.    * @param query 
  620.    * @param page 
  621.    * @param highlighterParam 
  622.    * @param writerConfig 
  623.    * @throws IOException 
  624.    */  
  625.   public static void pageQuery(IndexSearcher searcher,Directory directory,Query query,Page<Document> page,HighlighterParam highlighterParam,IndexWriterConfig writerConfig) throws IOException {  
  626.     IndexWriter writer = null;  
  627.     //若未设置高亮  
  628.     if(null == highlighterParam || !highlighterParam.isHighlight()) {  
  629.       pageQuery(searcher,directory,query, page);  
  630.     } else {  
  631.       int totalRecord = searchTotalRecord(searcher,query);  
  632.       System.out.println("totalRecord:" + totalRecord);  
  633.       //设置总记录数  
  634.       page.setTotalRecord(totalRecord);  
  635.       TopDocs topDocs = searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize());  
  636.       List<Document> docList = new ArrayList<Document>();  
  637.       ScoreDoc[] docs = topDocs.scoreDocs;  
  638.       int index = 0;  
  639.       writer = getIndexWrtier(directory, writerConfig);  
  640.       for (ScoreDoc scoreDoc : docs) {  
  641.         int docID = scoreDoc.doc;  
  642.         Document document = searcher.doc(docID);  
  643.         String content = document.get(highlighterParam.getFieldName());  
  644.         if(null != content && content.trim().length() > 0) {  
  645.           //创建高亮器  
  646.           Highlighter highlighter = LuceneUtils.createHighlighter(query,   
  647.             highlighterParam.getPrefix(), highlighterParam.getStuffix(),   
  648.             highlighterParam.getFragmenterLength());  
  649.           String text = highlight(document, highlighter, analyzer, highlighterParam.getFieldName());  
  650.           //若高亮后跟原始文本不相同,表示高亮成功  
  651.           if(!text.equals(content)) {  
  652.             Document tempdocument = new Document();  
  653.             List<IndexableField> indexableFieldList = document.getFields();  
  654.             if(null != indexableFieldList && indexableFieldList.size() > 0) {  
  655.               for(IndexableField field : indexableFieldList) {  
  656.                 if(field.name().equals(highlighterParam.getFieldName())) {  
  657.                   tempdocument.add(new TextField(field.name(), text, Field.Store.YES));  
  658.                 } else {  
  659.                   tempdocument.add(field);  
  660.                 }  
  661.               }  
  662.             }  
  663.             updateIndex(writer, new Term(highlighterParam.getFieldName(),content), tempdocument);  
  664.             document = tempdocument;  
  665.           }  
  666.         }  
  667.         if(index == docs.length - 1) {  
  668.           page.setAfterDoc(scoreDoc);  
  669.           page.setAfterDocId(docID);  
  670.         }  
  671.         docList.add(document);  
  672.         index++;  
  673.       }  
  674.       page.setItems(docList);  
  675.     }  
  676.     closeIndexReader(searcher.getIndexReader());  
  677.     closeIndexWriter(writer);  
  678.   }  
  679. }  
  680. package com.yida.framework.lucene5.util;  
  681. import java.util.ArrayList;  
  682. import java.util.Collection;  
  683. import java.util.List;  
  684. import org.apache.lucene.document.Document;  
  685. import org.apache.lucene.search.ScoreDoc;  
  686. public class Page<T> {  
  687.   /**当前第几页(从1开始计算)*/  
  688.   private int currentPage;  
  689.   /**每页显示几条*/  
  690.   private int pageSize;  
  691.   /**总记录数*/  
  692.   private int totalRecord;  
  693.   /**总页数*/  
  694.   private int totalPage;  
  695.   /**分页数据集合[用泛型T来限定集合元素类型]*/  
  696.   private Collection<T> items;  
  697.   /**当前显示起始索引(从零开始计算)*/  
  698.   private int startIndex;  
  699.   /**当前显示结束索引(从零开始计算)*/  
  700.   private int endIndex;  
  701.   /**一组最多显示几个页码[比如Google一组最多显示10个页码]*/  
  702.   private int groupSize;  
  703.   /**左边偏移量*/  
  704.   private int leftOffset = 5;  
  705.   /**右边偏移量*/  
  706.   private int rightOffset = 4;  
  707.   /**当前页码范围*/  
  708.   private String[] pageRange;  
  709.   /**分页数据*/  
  710.   private List<Document> docList;  
  711.   /**上一页最后一个ScoreDoc对象*/  
  712.   private ScoreDoc afterDoc;  
  713.   /**上一页最后一个ScoreDoc对象的Document对象ID*/  
  714.   private int afterDocId;  
  715.   public void setRangeIndex() {  
  716.     int groupSize = getGroupSize();  
  717.     int totalPage = getTotalPage();  
  718.     if(totalPage < 2) {  
  719.       startIndex = 0;  
  720.       endIndex = totalPage - startIndex;  
  721.     } else {  
  722.       int currentPage = getCurrentPage();  
  723.       if(groupSize >= totalPage) {  
  724.         startIndex = 0;  
  725.         endIndex = totalPage - startIndex - 1;  
  726.       } else {  
  727.         int leftOffset = getLeftOffset();  
  728.         int middleOffset = getMiddleOffset();  
  729.         if(-1 == middleOffset) {  
  730.           startIndex = 0;  
  731.           endIndex = groupSize - 1;  
  732.         } else if(currentPage <= leftOffset) {  
  733.           startIndex = 0;  
  734.           endIndex = groupSize - 1;  
  735.         } else {  
  736.           startIndex = currentPage - leftOffset - 1;  
  737.           if(currentPage + rightOffset > totalPage) {  
  738.             endIndex = totalPage - 1;  
  739.           } else {  
  740.             endIndex = currentPage + rightOffset - 1;  
  741.           }  
  742.         }  
  743.       }  
  744.     }  
  745.   }  
  746.   public int getCurrentPage() {  
  747.     if(currentPage <= 0) {  
  748.       currentPage = 1;  
  749.     } else {  
  750.       int totalPage = getTotalPage();  
  751.       if(totalPage > 0 && currentPage > getTotalPage()) {  
  752.         currentPage = totalPage;  
  753.       }  
  754.     }  
  755.     return currentPage;  
  756.   }  
  757.   public void setCurrentPage(int currentPage) {  
  758.     this.currentPage = currentPage;  
  759.   }  
  760.   public int getPageSize() {  
  761.     if(pageSize <= 0) {  
  762.       pageSize = 10;  
  763.     }  
  764.     return pageSize;  
  765.   }  
  766.   public void setPageSize(int pageSize) {  
  767.     this.pageSize = pageSize;  
  768.   }  
  769.   public int getTotalRecord() {  
  770.     return totalRecord;  
  771.   }  
  772.   public void setTotalRecord(int totalRecord) {  
  773.     this.totalRecord = totalRecord;  
  774.   }  
  775.   public int getTotalPage() {  
  776.     int totalRecord = getTotalRecord();  
  777.     if(totalRecord == 0) {  
  778.       totalPage = 0;  
  779.     } else {  
  780.       int pageSize = getPageSize();  
  781.       totalPage = totalRecord % pageSize == 0 ? totalRecord / pageSize : (totalRecord / pageSize) + 1;  
  782.     }  
  783.     return totalPage;  
  784.   }  
  785.   public void setTotalPage(int totalPage) {  
  786.     this.totalPage = totalPage;  
  787.   }  
  788.   public int getStartIndex() {  
  789.     return startIndex;  
  790.   }  
  791.   public void setStartIndex(int startIndex) {  
  792.     this.startIndex = startIndex;  
  793.   }  
  794.   public int getEndIndex() {  
  795.     return endIndex;  
  796.   }  
  797.   public void setEndIndex(int endIndex) {  
  798.     this.endIndex = endIndex;  
  799.   }  
  800.   public int getGroupSize() {  
  801.     if(groupSize <= 0) {  
  802.       groupSize = 10;  
  803.     }  
  804.     return groupSize;  
  805.   }  
  806.   public void setGroupSize(int groupSize) {  
  807.     this.groupSize = groupSize;  
  808.   }  
  809.   public int getLeftOffset() {  
  810.     leftOffset = getGroupSize() / 2;  
  811.     return leftOffset;  
  812.   }  
  813.   public void setLeftOffset(int leftOffset) {  
  814.     this.leftOffset = leftOffset;  
  815.   }  
  816.   public int getRightOffset() {  
  817.     int groupSize = getGroupSize();  
  818.     if(groupSize % 2 == 0) {  
  819.       rightOffset = (groupSize / 2) - 1;  
  820.     } else {  
  821.       rightOffset = groupSize / 2;  
  822.     }  
  823.     return rightOffset;  
  824.   }  
  825.   public void setRightOffset(int rightOffset) {  
  826.     this.rightOffset = rightOffset;  
  827.   }  
  828.   /**中心位置索引[从1开始计算]*/  
  829.   public int getMiddleOffset() {  
  830.     int groupSize = getGroupSize();  
  831.     int totalPage = getTotalPage();  
  832.     if(groupSize >= totalPage) {  
  833.       return -1;  
  834.     }  
  835.     return getLeftOffset() + 1;  
  836.   }  
  837.   public String[] getPageRange() {  
  838.     setRangeIndex();  
  839.     int size = endIndex - startIndex + 1;  
  840.     if(size <= 0) {  
  841.       return new String[0];  
  842.     }  
  843.     if(totalPage == 1) {  
  844.       return new String[] {"1"};  
  845.     }  
  846.     pageRange = new String[size];  
  847.     for(int i=0; i < size; i++) {  
  848.       pageRange[i] = (startIndex + i + 1) + "";  
  849.     }  
  850.     return pageRange;  
  851.   }  
  852.   public void setPageRange(String[] pageRange) {  
  853.     this.pageRange = pageRange;  
  854.   }  
  855.   public Collection<T> getItems() {  
  856.     return items;  
  857.   }  
  858.   public void setItems(Collection<T> items) {  
  859.     this.items = items;  
  860.   }  
  861.   public List<Document> getDocList() {  
  862.     return docList;  
  863.   }  
  864.   public void setDocList(List<Document> docList) {  
  865.     this.docList = docList;  
  866.   }  
  867.   public ScoreDoc getAfterDoc() {  
  868.     setAfterDocId(afterDocId);  
  869.     return afterDoc;  
  870.   }  
  871.   public void setAfterDoc(ScoreDoc afterDoc) {  
  872.     this.afterDoc = afterDoc;  
  873.   }  
  874.   public int getAfterDocId() {  
  875.     return afterDocId;  
  876.   }  
  877.   public void setAfterDocId(int afterDocId) {  
  878.     this.afterDocId = afterDocId;  
  879.     if(null == afterDoc) {  
  880.       this.afterDoc = new ScoreDoc(afterDocId, 1.0f);  
  881.     }  
  882.   }  
  883.   public Page() {}  
  884.   public Page(int currentPage, int pageSize) {  
  885.     this.currentPage = currentPage;  
  886.     this.pageSize = pageSize;  
  887.   }  
  888.   public Page(int currentPage, int pageSize, Collection<T> items) {  
  889.     this.currentPage = currentPage;  
  890.     this.pageSize = pageSize;  
  891.     this.items = items;  
  892.   }  
  893.   public Page(int currentPage, int pageSize, Collection<T> items, int groupSize) {  
  894.     this.currentPage = currentPage;  
  895.     this.pageSize = pageSize;  
  896.     this.items = items;  
  897.     this.groupSize = groupSize;  
  898.   }  
  899.   public Page(int currentPage, int pageSize, int groupSize, int afterDocId) {  
  900.     this.currentPage = currentPage;  
  901.     this.pageSize = pageSize;  
  902.     this.groupSize = groupSize;  
  903.     this.afterDocId = afterDocId;  
  904.   }  
  905.   public static void main(String[] args) {  
  906.     Collection<Integer> items = new ArrayList<Integer>();  
  907.     int totalRecord = 201;  
  908.     for(int i=0; i < totalRecord; i++) {  
  909.       items.add(new Integer(i));  
  910.     }  
  911.     Page<Integer> page = new Page<Integer>(1,10,items,10);  
  912.     page.setTotalRecord(totalRecord);  
  913.     int totalPage = page.getTotalPage();  
  914.     for(int i=0; i < totalPage; i++) {  
  915.       page.setCurrentPage(i+1);  
  916.       String[] pageRange = page.getPageRange();  
  917.       System.out.println("当前第" + page.currentPage + "页");  
  918.       for(int j=0; j < pageRange.length; j++) {  
  919.         System.out.print(pageRange[j] + "  ");  
  920.       }  
  921.       System.out.println("\n");  
  922.     }     
  923.   }  
  924. }  
  925. package com.yida.framework.lucene5.util;  
  926. /** 
  927.  * @ClassName: HighlighterParam 
  928.  * @Description: 高亮器参数对象 
  929.  * @author Lanxiaowei 
  930.  * @date 2014-3-30 下午12:22:08 
  931.  */  
  932. public class HighlighterParam {  
  933.   /**是否需要设置高亮*/  
  934.   private boolean highlight;  
  935.   /**需要设置高亮的属性名*/  
  936.   private String fieldName;  
  937.   /**高亮前缀*/  
  938.   private String prefix;  
  939.   /**高亮后缀*/  
  940.   private String stuffix;  
  941.   /**显示摘要最大长度*/  
  942.   private int fragmenterLength;  
  943.   public boolean isHighlight() {  
  944.     return highlight;  
  945.   }  
  946.   public void setHighlight(boolean highlight) {  
  947.     this.highlight = highlight;  
  948.   }  
  949.   public String getFieldName() {  
  950.     return fieldName;  
  951.   }  
  952.   public void setFieldName(String fieldName) {  
  953.     this.fieldName = fieldName;  
  954.   }  
  955.   public String getPrefix() {  
  956.     return prefix;  
  957.   }  
  958.   public void setPrefix(String prefix) {  
  959.     this.prefix = prefix;  
  960.   }  
  961.   public String getStuffix() {  
  962.     return stuffix;  
  963.   }  
  964.   public void setStuffix(String stuffix) {  
  965.     this.stuffix = stuffix;  
  966.   }  
  967.   public int getFragmenterLength() {  
  968.     return fragmenterLength;  
  969.   }  
  970.   public void setFragmenterLength(int fragmenterLength) {  
  971.     this.fragmenterLength = fragmenterLength;  
  972.   }  
  973.   public HighlighterParam(boolean highlight, String fieldName, String prefix, String stuffix, int fragmenterLength) {  
  974.     this.highlight = highlight;  
  975.     this.fieldName = fieldName;  
  976.     this.prefix = prefix;  
  977.     this.stuffix = stuffix;  
  978.     this.fragmenterLength = fragmenterLength;  
  979.   }  
  980.     
  981.   public HighlighterParam(boolean highlight, String fieldName, int fragmenterLength) {  
  982.     this.highlight = highlight;  
  983.     this.fieldName = fieldName;  
  984.     this.fragmenterLength = fragmenterLength;  
  985.   }  
  986.     
  987.   public HighlighterParam(boolean highlight, String fieldName, String prefix, String stuffix) {  
  988.     this.highlight = highlight;  
  989.     this.fieldName = fieldName;  
  990.     this.prefix = prefix;  
  991.     this.stuffix = stuffix;  
  992.   }  
  993.   public HighlighterParam() {  
  994.   }  
  995. }  
工具类对IndexWriter,IndexReader,IndexSearcher,Analyzer,QueryParser等Lucene这些常用操作对象的获取进行了封装,其中IndexWriter采用了单例模式,确保始终只有一个对象实例,因为Lucene限制了索引写操作是阻塞的,即同一时刻只能有一个IndexWriter在执行写操作,直到indexWriter释放lock,而索引读的操作是可以并发进行的。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多