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

简介:

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

 

Java代码   收藏代码
  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. }  

 

Java代码   收藏代码
  1. package com.yida.framework.lucene5.util;  
  2.   
  3. import java.io.IOException;  
  4. import java.nio.file.Paths;  
  5. import java.util.ArrayList;  
  6. import java.util.Collections;  
  7. import java.util.List;  
  8. import java.util.Set;  
  9. import java.util.concurrent.ExecutorService;  
  10.   
  11. import org.ansj.lucene5.AnsjAnalyzer;  
  12. import org.apache.lucene.analysis.Analyzer;  
  13. import org.apache.lucene.document.Document;  
  14. import org.apache.lucene.document.Field;  
  15. import org.apache.lucene.document.TextField;  
  16. import org.apache.lucene.index.IndexReader;  
  17. import org.apache.lucene.index.IndexWriter;  
  18. import org.apache.lucene.index.IndexWriterConfig;  
  19. import org.apache.lucene.index.IndexableField;  
  20. import org.apache.lucene.index.Term;  
  21. import org.apache.lucene.queryparser.classic.QueryParser;  
  22. import org.apache.lucene.search.IndexSearcher;  
  23. import org.apache.lucene.search.Query;  
  24. import org.apache.lucene.search.ScoreDoc;  
  25. import org.apache.lucene.search.TopDocs;  
  26. import org.apache.lucene.search.highlight.Formatter;  
  27. import org.apache.lucene.search.highlight.Fragmenter;  
  28. import org.apache.lucene.search.highlight.Highlighter;  
  29. import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;  
  30. import org.apache.lucene.search.highlight.QueryScorer;  
  31. import org.apache.lucene.search.highlight.Scorer;  
  32. import org.apache.lucene.search.highlight.SimpleFragmenter;  
  33. import org.apache.lucene.search.highlight.SimpleHTMLFormatter;  
  34. import org.apache.lucene.store.Directory;  
  35. import org.apache.lucene.store.FSDirectory;  
  36.   
  37. /** 
  38.  * Lucene工具类(基于Lucene5.0封装) 
  39.  * @author Lanxiaowei 
  40.  * 
  41.  */  
  42. public class LuceneUtils {  
  43.     private static final LuceneManager luceneManager = LuceneManager.getInstance();  
  44.     private static Analyzer analyzer = new AnsjAnalyzer();  
  45.       
  46.     /** 
  47.      * 打开索引目录 
  48.      *  
  49.      * @param luceneDir 
  50.      * @return 
  51.      * @throws IOException 
  52.      */  
  53.     public static FSDirectory openFSDirectory(String luceneDir) {  
  54.         FSDirectory directory = null;  
  55.         try {  
  56.             directory = FSDirectory.open(Paths.get(luceneDir));  
  57.             /** 
  58.              * 注意:isLocked方法内部会试图去获取Lock,如果获取到Lock,会关闭它,否则return false表示索引目录没有被锁, 
  59.              * 这也就是为什么unlock方法被从IndexWriter类中移除的原因 
  60.              */  
  61.             IndexWriter.isLocked(directory);  
  62.         } catch (IOException e) {  
  63.             e.printStackTrace();  
  64.         }  
  65.         return directory;  
  66.     }  
  67.       
  68.     /** 
  69.      * 关闭索引目录并销毁 
  70.      * @param directory 
  71.      * @throws IOException 
  72.      */  
  73.     public static void closeDirectory(Directory directory) throws IOException {  
  74.         if (null != directory) {  
  75.             directory.close();  
  76.             directory = null;  
  77.         }  
  78.     }  
  79.       
  80.     /** 
  81.      * 获取IndexWriter 
  82.      * @param dir 
  83.      * @param config 
  84.      * @return 
  85.      */  
  86.     public static IndexWriter getIndexWrtier(Directory dir, IndexWriterConfig config) {  
  87.         return luceneManager.getIndexWriter(dir, config);  
  88.     }  
  89.       
  90.     /** 
  91.      * 获取IndexWriter 
  92.      * @param dir 
  93.      * @param config 
  94.      * @return 
  95.      */  
  96.     public static IndexWriter getIndexWrtier(String directoryPath, IndexWriterConfig config) {  
  97.         FSDirectory directory = openFSDirectory(directoryPath);  
  98.         return luceneManager.getIndexWriter(directory, config);  
  99.     }  
  100.       
  101.     /** 
  102.      * 获取IndexReader 
  103.      * @param dir 
  104.      * @param enableNRTReader  是否开启NRTReader 
  105.      * @return 
  106.      */  
  107.     public static IndexReader getIndexReader(Directory dir,boolean enableNRTReader) {  
  108.         return luceneManager.getIndexReader(dir, enableNRTReader);  
  109.     }  
  110.       
  111.     /** 
  112.      * 获取IndexReader(默认不启用NRTReader) 
  113.      * @param dir 
  114.      * @return 
  115.      */  
  116.     public static IndexReader getIndexReader(Directory dir) {  
  117.         return luceneManager.getIndexReader(dir);  
  118.     }  
  119.       
  120.     /** 
  121.      * 获取IndexSearcher 
  122.      * @param reader    IndexReader对象 
  123.      * @param executor  如果你需要开启多线程查询,请提供ExecutorService对象参数 
  124.      * @return 
  125.      */  
  126.     public static IndexSearcher getIndexSearcher(IndexReader reader,ExecutorService executor) {  
  127.         return luceneManager.getIndexSearcher(reader, executor);  
  128.     }  
  129.       
  130.     /** 
  131.      * 获取IndexSearcher(不支持多线程查询) 
  132.      * @param reader    IndexReader对象 
  133.      * @return 
  134.      */  
  135.     public static IndexSearcher getIndexSearcher(IndexReader reader) {  
  136.         return luceneManager.getIndexSearcher(reader);  
  137.     }  
  138.       
  139.     /** 
  140.      * 创建QueryParser对象 
  141.      * @param field 
  142.      * @param analyzer 
  143.      * @return 
  144.      */  
  145.     public static QueryParser createQueryParser(String field, Analyzer analyzer) {  
  146.         return new QueryParser(field, analyzer);  
  147.     }  
  148.       
  149.     /** 
  150.      * 关闭IndexReader 
  151.      * @param reader 
  152.      */  
  153.     public static void closeIndexReader(IndexReader reader) {  
  154.         if (null != reader) {  
  155.             try {  
  156.                 reader.close();  
  157.                 reader = null;  
  158.             } catch (IOException e) {  
  159.                 e.printStackTrace();  
  160.             }  
  161.         }  
  162.     }  
  163.       
  164.     /** 
  165.      * 关闭IndexWriter 
  166.      * @param writer 
  167.      */  
  168.     public static void closeIndexWriter(IndexWriter writer) {  
  169.         if(null != writer) {  
  170.             try {  
  171.                 writer.close();  
  172.                 writer = null;  
  173.             } catch (IOException e) {  
  174.                 e.printStackTrace();  
  175.             }  
  176.         }  
  177.     }  
  178.       
  179.     /** 
  180.      * 关闭IndexReader和IndexWriter 
  181.      * @param reader 
  182.      * @param writer 
  183.      */  
  184.     public static void closeAll(IndexReader reader, IndexWriter writer) {  
  185.         closeIndexReader(reader);  
  186.         closeIndexWriter(writer);  
  187.     }  
  188.       
  189.     /** 
  190.      * 删除索引[注意:请自己关闭IndexWriter对象] 
  191.      * @param writer 
  192.      * @param field 
  193.      * @param value 
  194.      */  
  195.     public static void deleteIndex(IndexWriter writer, String field, String value) {  
  196.         try {  
  197.             writer.deleteDocuments(new Term[] {new Term(field,value)});  
  198.         } catch (IOException e) {  
  199.             e.printStackTrace();  
  200.         }  
  201.     }  
  202.       
  203.     /** 
  204.      * 删除索引[注意:请自己关闭IndexWriter对象] 
  205.      * @param writer 
  206.      * @param query 
  207.      */  
  208.     public static void deleteIndex(IndexWriter writer, Query query) {  
  209.         try {  
  210.             writer.deleteDocuments(query);  
  211.         } catch (IOException e) {  
  212.             e.printStackTrace();  
  213.         }  
  214.     }  
  215.       
  216.     /** 
  217.      * 批量删除索引[注意:请自己关闭IndexWriter对象] 
  218.      * @param writer 
  219.      * @param terms 
  220.      */  
  221.     public static void deleteIndexs(IndexWriter writer,Term[] terms) {  
  222.         try {  
  223.             writer.deleteDocuments(terms);  
  224.         } catch (IOException e) {  
  225.             e.printStackTrace();  
  226.         }  
  227.     }  
  228.       
  229.     /** 
  230.      * 批量删除索引[注意:请自己关闭IndexWriter对象] 
  231.      * @param writer 
  232.      * @param querys 
  233.      */  
  234.     public static void deleteIndexs(IndexWriter writer,Query[] querys) {  
  235.         try {  
  236.             writer.deleteDocuments(querys);  
  237.         } catch (IOException e) {  
  238.             e.printStackTrace();  
  239.         }  
  240.     }  
  241.       
  242.     /** 
  243.      * 删除所有索引文档 
  244.      * @param writer 
  245.      */  
  246.     public static void deleteAllIndex(IndexWriter writer) {  
  247.         try {  
  248.             writer.deleteAll();  
  249.         } catch (IOException e) {  
  250.             e.printStackTrace();  
  251.         }  
  252.     }  
  253.       
  254.     /** 
  255.      * 更新索引文档 
  256.      * @param writer 
  257.      * @param term 
  258.      * @param document 
  259.      */  
  260.     public static void updateIndex(IndexWriter writer,Term term,Document document) {  
  261.         try {  
  262.             writer.updateDocument(term, document);  
  263.         } catch (IOException e) {  
  264.             e.printStackTrace();  
  265.         }  
  266.     }  
  267.       
  268.     /** 
  269.      * 更新索引文档 
  270.      * @param writer 
  271.      * @param term 
  272.      * @param document 
  273.      */  
  274.     public static void updateIndex(IndexWriter writer,String field,String value,Document document) {  
  275.         updateIndex(writer, new Term(field, value), document);  
  276.     }  
  277.       
  278.     /** 
  279.      * 添加索引文档 
  280.      * @param writer 
  281.      * @param doc 
  282.      */  
  283.     public static void addIndex(IndexWriter writer, Document document) {  
  284.         updateIndex(writer, null, document);  
  285.     }  
  286.       
  287.     /** 
  288.      * 索引文档查询 
  289.      * @param searcher 
  290.      * @param query 
  291.      * @return 
  292.      */  
  293.     public static List<Document> query(IndexSearcher searcher,Query query) {  
  294.         TopDocs topDocs = null;  
  295.         try {  
  296.             topDocs = searcher.search(query, Integer.MAX_VALUE);  
  297.         } catch (IOException e) {  
  298.             e.printStackTrace();  
  299.         }  
  300.         ScoreDoc[] scores = topDocs.scoreDocs;  
  301.         int length = scores.length;  
  302.         if (length <= 0) {  
  303.             return Collections.emptyList();  
  304.         }  
  305.         List<Document> docList = new ArrayList<Document>();  
  306.         try {  
  307.             for (int i = 0; i < length; i++) {  
  308.                 Document doc = searcher.doc(scores[i].doc);  
  309.                 docList.add(doc);  
  310.             }  
  311.         } catch (IOException e) {  
  312.             e.printStackTrace();  
  313.         }  
  314.         return docList;  
  315.     }  
  316.       
  317.     /** 
  318.      * 返回索引文档的总数[注意:请自己手动关闭IndexReader] 
  319.      * @param reader 
  320.      * @return 
  321.      */  
  322.     public static int getIndexTotalCount(IndexReader reader) {  
  323.         return reader.numDocs();  
  324.     }  
  325.       
  326.     /** 
  327.      * 返回索引文档中最大文档ID[注意:请自己手动关闭IndexReader] 
  328.      * @param reader 
  329.      * @return 
  330.      */  
  331.     public static int getMaxDocId(IndexReader reader) {  
  332.         return reader.maxDoc();  
  333.     }  
  334.       
  335.     /** 
  336.      * 返回已经删除尚未提交的文档总数[注意:请自己手动关闭IndexReader] 
  337.      * @param reader 
  338.      * @return 
  339.      */  
  340.     public static int getDeletedDocNum(IndexReader reader) {  
  341.         return getMaxDocId(reader) - getIndexTotalCount(reader);  
  342.     }  
  343.       
  344.     /** 
  345.      * 根据docId查询索引文档 
  346.      * @param reader         IndexReader对象 
  347.      * @param docID          documentId 
  348.      * @param fieldsToLoad   需要返回的field 
  349.      * @return 
  350.      */  
  351.     public static Document findDocumentByDocId(IndexReader reader,int docID, Set<String> fieldsToLoad) {  
  352.         try {  
  353.             return reader.document(docID, fieldsToLoad);  
  354.         } catch (IOException e) {  
  355.             return null;  
  356.         }  
  357.     }  
  358.       
  359.     /** 
  360.      * 根据docId查询索引文档 
  361.      * @param reader         IndexReader对象 
  362.      * @param docID          documentId 
  363.      * @return 
  364.      */  
  365.     public static Document findDocumentByDocId(IndexReader reader,int docID) {  
  366.         return findDocumentByDocId(reader, docID, null);  
  367.     }  
  368.       
  369.     /** 
  370.      * @Title: createHighlighter 
  371.      * @Description: 创建高亮器 
  372.      * @param query             索引查询对象 
  373.      * @param prefix            高亮前缀字符串 
  374.      * @param stuffix           高亮后缀字符串 
  375.      * @param fragmenterLength  摘要最大长度 
  376.      * @return 
  377.      */  
  378.     public static Highlighter createHighlighter(Query query, String prefix, String stuffix, int fragmenterLength) {  
  379.         Formatter formatter = new SimpleHTMLFormatter((prefix == null || prefix.trim().length() == 0) ?   
  380.             "<font color=\"red\">" : prefix, (stuffix == null || stuffix.trim().length() == 0)?"</font>" : stuffix);  
  381.         Scorer fragmentScorer = new QueryScorer(query);  
  382.         Highlighter highlighter = new Highlighter(formatter, fragmentScorer);  
  383.         Fragmenter fragmenter = new SimpleFragmenter(fragmenterLength <= 0 ? 50 : fragmenterLength);  
  384.         highlighter.setTextFragmenter(fragmenter);  
  385.         return highlighter;  
  386.     }  
  387.       
  388.     /** 
  389.      * @Title: highlight 
  390.      * @Description: 生成高亮文本 
  391.      * @param document          索引文档对象 
  392.      * @param highlighter       高亮器 
  393.      * @param analyzer          索引分词器 
  394.      * @param field             高亮字段 
  395.      * @return 
  396.      * @throws IOException 
  397.      * @throws InvalidTokenOffsetsException 
  398.      */  
  399.     public static String highlight(Document document,Highlighter highlighter,Analyzer analyzer,String field) throws IOException {  
  400.         List<IndexableField> list = document.getFields();  
  401.         for (IndexableField fieldable : list) {  
  402.             String fieldValue = fieldable.stringValue();  
  403.             if(fieldable.name().equals(field)) {  
  404.                 try {  
  405.                     fieldValue = highlighter.getBestFragment(analyzer, field, fieldValue);  
  406.                 } catch (InvalidTokenOffsetsException e) {  
  407.                     fieldValue = fieldable.stringValue();  
  408.                 }  
  409.                 return (fieldValue == null || fieldValue.trim().length() == 0)? fieldable.stringValue() : fieldValue;  
  410.             }  
  411.         }  
  412.         return null;  
  413.     }  
  414.       
  415.     /** 
  416.      * @Title: searchTotalRecord 
  417.      * @Description: 获取符合条件的总记录数 
  418.      * @param query 
  419.      * @return 
  420.      * @throws IOException 
  421.      */  
  422.     public static int searchTotalRecord(IndexSearcher search,Query query) {  
  423.         ScoreDoc[] docs = null;  
  424.         try {  
  425.             TopDocs topDocs = search.search(query, Integer.MAX_VALUE);  
  426.             if(topDocs == null || topDocs.scoreDocs == null || topDocs.scoreDocs.length == 0) {  
  427.                 return 0;  
  428.             }  
  429.             docs = topDocs.scoreDocs;  
  430.         } catch (IOException e) {  
  431.             e.printStackTrace();  
  432.         }  
  433.         return docs.length;  
  434.     }  
  435.       
  436.     /** 
  437.      * @Title: pageQuery 
  438.      * @Description: Lucene分页查询 
  439.      * @param searcher 
  440.      * @param query 
  441.      * @param page 
  442.      * @throws IOException 
  443.      */  
  444.     public static void pageQuery(IndexSearcher searcher,Directory directory,Query query,Page<Document> page) {  
  445.         int totalRecord = searchTotalRecord(searcher,query);  
  446.         //设置总记录数  
  447.         page.setTotalRecord(totalRecord);  
  448.         TopDocs topDocs = null;  
  449.         try {  
  450.             topDocs = searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize());  
  451.         } catch (IOException e) {  
  452.             e.printStackTrace();  
  453.         }  
  454.         List<Document> docList = new ArrayList<Document>();  
  455.         ScoreDoc[] docs = topDocs.scoreDocs;  
  456.         int index = 0;  
  457.         for (ScoreDoc scoreDoc : docs) {  
  458.             int docID = scoreDoc.doc;  
  459.             Document document = null;  
  460.             try {  
  461.                 document = searcher.doc(docID);  
  462.             } catch (IOException e) {  
  463.                 e.printStackTrace();  
  464.             }  
  465.             if(index == docs.length - 1) {  
  466.                 page.setAfterDoc(scoreDoc);  
  467.                 page.setAfterDocId(docID);  
  468.             }  
  469.             docList.add(document);  
  470.             index++;  
  471.         }  
  472.         page.setItems(docList);  
  473.         closeIndexReader(searcher.getIndexReader());  
  474.     }  
  475.       
  476.     /** 
  477.      * @Title: pageQuery 
  478.      * @Description: 分页查询[如果设置了高亮,则会更新索引文档] 
  479.      * @param searcher 
  480.      * @param directory 
  481.      * @param query 
  482.      * @param page 
  483.      * @param highlighterParam 
  484.      * @param writerConfig 
  485.      * @throws IOException 
  486.      */  
  487.     public static void pageQuery(IndexSearcher searcher,Directory directory,Query query,Page<Document> page,HighlighterParam highlighterParam,IndexWriterConfig writerConfig) throws IOException {  
  488.         IndexWriter writer = null;  
  489.         //若未设置高亮  
  490.         if(null == highlighterParam || !highlighterParam.isHighlight()) {  
  491.             pageQuery(searcher,directory,query, page);  
  492.         } else {  
  493.             int totalRecord = searchTotalRecord(searcher,query);  
  494.             System.out.println("totalRecord:" + totalRecord);  
  495.             //设置总记录数  
  496.             page.setTotalRecord(totalRecord);  
  497.             TopDocs topDocs = searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize());  
  498.             List<Document> docList = new ArrayList<Document>();  
  499.             ScoreDoc[] docs = topDocs.scoreDocs;  
  500.             int index = 0;  
  501.             writer = getIndexWrtier(directory, writerConfig);  
  502.             for (ScoreDoc scoreDoc : docs) {  
  503.                 int docID = scoreDoc.doc;  
  504.                 Document document = searcher.doc(docID);  
  505.                 String content = document.get(highlighterParam.getFieldName());  
  506.                 if(null != content && content.trim().length() > 0) {  
  507.                     //创建高亮器  
  508.                     Highlighter highlighter = LuceneUtils.createHighlighter(query,   
  509.                         highlighterParam.getPrefix(), highlighterParam.getStuffix(),   
  510.                         highlighterParam.getFragmenterLength());  
  511.                     String text = highlight(document, highlighter, analyzer, highlighterParam.getFieldName());  
  512.                     //若高亮后跟原始文本不相同,表示高亮成功  
  513.                     if(!text.equals(content)) {  
  514.                         Document tempdocument = new Document();  
  515.                         List<IndexableField> indexableFieldList = document.getFields();  
  516.                         if(null != indexableFieldList && indexableFieldList.size() > 0) {  
  517.                             for(IndexableField field : indexableFieldList) {  
  518.                                 if(field.name().equals(highlighterParam.getFieldName())) {  
  519.                                     tempdocument.add(new TextField(field.name(), text, Field.Store.YES));  
  520.                                 } else {  
  521.                                     tempdocument.add(field);  
  522.                                 }  
  523.                             }  
  524.                         }  
  525.                         updateIndex(writer, new Term(highlighterParam.getFieldName(),content), tempdocument);  
  526.                         document = tempdocument;  
  527.                     }  
  528.                 }  
  529.                 if(index == docs.length - 1) {  
  530.                     page.setAfterDoc(scoreDoc);  
  531.                     page.setAfterDocId(docID);  
  532.                 }  
  533.                 docList.add(document);  
  534.                 index++;  
  535.             }  
  536.             page.setItems(docList);  
  537.         }  
  538.         closeIndexReader(searcher.getIndexReader());  
  539.         closeIndexWriter(writer);  
  540.     }  
  541. }  

 

Java代码   收藏代码
  1. package com.yida.framework.lucene5.util;  
  2. import java.util.ArrayList;  
  3. import java.util.Collection;  
  4. import java.util.List;  
  5.   
  6. import org.apache.lucene.document.Document;  
  7. import org.apache.lucene.search.ScoreDoc;  
  8. public class Page<T> {  
  9.     /**当前第几页(从1开始计算)*/  
  10.     private int currentPage;  
  11.     /**每页显示几条*/  
  12.     private int pageSize;  
  13.     /**总记录数*/  
  14.     private int totalRecord;  
  15.     /**总页数*/  
  16.     private int totalPage;  
  17.     /**分页数据集合[用泛型T来限定集合元素类型]*/  
  18.     private Collection<T> items;  
  19.     /**当前显示起始索引(从零开始计算)*/  
  20.     private int startIndex;  
  21.     /**当前显示结束索引(从零开始计算)*/  
  22.     private int endIndex;  
  23.     /**一组最多显示几个页码[比如Google一组最多显示10个页码]*/  
  24.     private int groupSize;  
  25.       
  26.     /**左边偏移量*/  
  27.     private int leftOffset = 5;  
  28.     /**右边偏移量*/  
  29.     private int rightOffset = 4;  
  30.     /**当前页码范围*/  
  31.     private String[] pageRange;  
  32.       
  33.     /**分页数据*/  
  34.     private List<Document> docList;  
  35.     /**上一页最后一个ScoreDoc对象*/  
  36.     private ScoreDoc afterDoc;  
  37.       
  38.     /**上一页最后一个ScoreDoc对象的Document对象ID*/  
  39.     private int afterDocId;  
  40.   
  41.     public void setRangeIndex() {  
  42.         int groupSize = getGroupSize();  
  43.         int totalPage = getTotalPage();  
  44.         if(totalPage < 2) {  
  45.             startIndex = 0;  
  46.             endIndex = totalPage - startIndex;  
  47.         } else {  
  48.             int currentPage = getCurrentPage();  
  49.             if(groupSize >= totalPage) {  
  50.                 startIndex = 0;  
  51.                 endIndex = totalPage - startIndex - 1;  
  52.             } else {  
  53.                 int leftOffset = getLeftOffset();  
  54.                 int middleOffset = getMiddleOffset();  
  55.                 if(-1 == middleOffset) {  
  56.                     startIndex = 0;  
  57.                     endIndex = groupSize - 1;  
  58.                 } else if(currentPage <= leftOffset) {  
  59.                     startIndex = 0;  
  60.                     endIndex = groupSize - 1;  
  61.                 } else {  
  62.                     startIndex = currentPage - leftOffset - 1;  
  63.                     if(currentPage + rightOffset > totalPage) {  
  64.                         endIndex = totalPage - 1;  
  65.                     } else {  
  66.                         endIndex = currentPage + rightOffset - 1;  
  67.                     }  
  68.                 }  
  69.             }  
  70.         }  
  71.     }  
  72.       
  73.     public int getCurrentPage() {  
  74.         if(currentPage <= 0) {  
  75.             currentPage = 1;  
  76.         } else {  
  77.             int totalPage = getTotalPage();  
  78.             if(totalPage > 0 && currentPage > getTotalPage()) {  
  79.                 currentPage = totalPage;  
  80.             }  
  81.         }  
  82.         return currentPage;  
  83.     }  
  84.     public void setCurrentPage(int currentPage) {  
  85.         this.currentPage = currentPage;  
  86.     }  
  87.     public int getPageSize() {  
  88.         if(pageSize <= 0) {  
  89.             pageSize = 10;  
  90.         }  
  91.         return pageSize;  
  92.     }  
  93.     public void setPageSize(int pageSize) {  
  94.         this.pageSize = pageSize;  
  95.     }  
  96.     public int getTotalRecord() {  
  97.         return totalRecord;  
  98.     }  
  99.     public void setTotalRecord(int totalRecord) {  
  100.         this.totalRecord = totalRecord;  
  101.     }  
  102.     public int getTotalPage() {  
  103.         int totalRecord = getTotalRecord();  
  104.         if(totalRecord == 0) {  
  105.             totalPage = 0;  
  106.         } else {  
  107.             int pageSize = getPageSize();  
  108.             totalPage = totalRecord % pageSize == 0 ? totalRecord / pageSize : (totalRecord / pageSize) + 1;  
  109.         }  
  110.         return totalPage;  
  111.     }  
  112.     public void setTotalPage(int totalPage) {  
  113.         this.totalPage = totalPage;  
  114.     }  
  115.       
  116.     public int getStartIndex() {  
  117.         return startIndex;  
  118.     }  
  119.     public void setStartIndex(int startIndex) {  
  120.         this.startIndex = startIndex;  
  121.     }  
  122.       
  123.     public int getEndIndex() {  
  124.         return endIndex;  
  125.     }  
  126.     public void setEndIndex(int endIndex) {  
  127.         this.endIndex = endIndex;  
  128.     }  
  129.     public int getGroupSize() {  
  130.         if(groupSize <= 0) {  
  131.             groupSize = 10;  
  132.         }  
  133.         return groupSize;  
  134.     }  
  135.     public void setGroupSize(int groupSize) {  
  136.         this.groupSize = groupSize;  
  137.     }  
  138.       
  139.     public int getLeftOffset() {  
  140.         leftOffset = getGroupSize() / 2;  
  141.         return leftOffset;  
  142.           
  143.     }  
  144.     public void setLeftOffset(int leftOffset) {  
  145.         this.leftOffset = leftOffset;  
  146.     }  
  147.     public int getRightOffset() {  
  148.         int groupSize = getGroupSize();  
  149.         if(groupSize % 2 == 0) {  
  150.             rightOffset = (groupSize / 2) - 1;  
  151.         } else {  
  152.             rightOffset = groupSize / 2;  
  153.         }  
  154.         return rightOffset;  
  155.     }  
  156.     public void setRightOffset(int rightOffset) {  
  157.         this.rightOffset = rightOffset;  
  158.     }  
  159.       
  160.     /**中心位置索引[从1开始计算]*/  
  161.     public int getMiddleOffset() {  
  162.         int groupSize = getGroupSize();  
  163.         int totalPage = getTotalPage();  
  164.         if(groupSize >= totalPage) {  
  165.             return -1;  
  166.         }  
  167.         return getLeftOffset() + 1;  
  168.     }  
  169.     public String[] getPageRange() {  
  170.         setRangeIndex();  
  171.         int size = endIndex - startIndex + 1;  
  172.         if(size <= 0) {  
  173.             return new String[0];  
  174.         }  
  175.         if(totalPage == 1) {  
  176.             return new String[] {"1"};  
  177.         }  
  178.         pageRange = new String[size];  
  179.         for(int i=0; i < size; i++) {  
  180.             pageRange[i] = (startIndex + i + 1) + "";  
  181.         }  
  182.         return pageRange;  
  183.     }  
  184.   
  185.     public void setPageRange(String[] pageRange) {  
  186.         this.pageRange = pageRange;  
  187.     }  
  188.   
  189.     public Collection<T> getItems() {  
  190.         return items;  
  191.     }  
  192.     public void setItems(Collection<T> items) {  
  193.         this.items = items;  
  194.     }  
  195.       
  196.     public List<Document> getDocList() {  
  197.         return docList;  
  198.     }  
  199.   
  200.     public void setDocList(List<Document> docList) {  
  201.         this.docList = docList;  
  202.     }  
  203.   
  204.     public ScoreDoc getAfterDoc() {  
  205.         setAfterDocId(afterDocId);  
  206.         return afterDoc;  
  207.     }  
  208.   
  209.     public void setAfterDoc(ScoreDoc afterDoc) {  
  210.         this.afterDoc = afterDoc;  
  211.     }  
  212.       
  213.     public int getAfterDocId() {  
  214.         return afterDocId;  
  215.     }  
  216.   
  217.     public void setAfterDocId(int afterDocId) {  
  218.         this.afterDocId = afterDocId;  
  219.         if(null == afterDoc) {  
  220.             this.afterDoc = new ScoreDoc(afterDocId, 1.0f);  
  221.         }  
  222.     }  
  223.       
  224.     public Page() {}  
  225.   
  226.     public Page(int currentPage, int pageSize) {  
  227.         this.currentPage = currentPage;  
  228.         this.pageSize = pageSize;  
  229.     }  
  230.   
  231.     public Page(int currentPage, int pageSize, Collection<T> items) {  
  232.         this.currentPage = currentPage;  
  233.         this.pageSize = pageSize;  
  234.         this.items = items;  
  235.     }  
  236.   
  237.     public Page(int currentPage, int pageSize, Collection<T> items, int groupSize) {  
  238.         this.currentPage = currentPage;  
  239.         this.pageSize = pageSize;  
  240.         this.items = items;  
  241.         this.groupSize = groupSize;  
  242.     }  
  243.   
  244.     public Page(int currentPage, int pageSize, int groupSize, int afterDocId) {  
  245.         this.currentPage = currentPage;  
  246.         this.pageSize = pageSize;  
  247.         this.groupSize = groupSize;  
  248.         this.afterDocId = afterDocId;  
  249.     }  
  250.   
  251.     public static void main(String[] args) {  
  252.         Collection<Integer> items = new ArrayList<Integer>();  
  253.         int totalRecord = 201;  
  254.         for(int i=0; i < totalRecord; i++) {  
  255.             items.add(new Integer(i));  
  256.         }  
  257.         Page<Integer> page = new Page<Integer>(1,10,items,10);  
  258.         page.setTotalRecord(totalRecord);  
  259.         int totalPage = page.getTotalPage();  
  260.         for(int i=0; i < totalPage; i++) {  
  261.             page.setCurrentPage(i+1);  
  262.             String[] pageRange = page.getPageRange();  
  263.             System.out.println("当前第" + page.currentPage + "页");  
  264.             for(int j=0; j < pageRange.length; j++) {  
  265.                 System.out.print(pageRange[j] + "  ");  
  266.             }  
  267.             System.out.println("\n");  
  268.         }     
  269.     }  
  270. }  

 

Java代码   收藏代码
  1. package com.yida.framework.lucene5.util;  
  2. /** 
  3.  * @ClassName: HighlighterParam 
  4.  * @Description: 高亮器参数对象 
  5.  * @author Lanxiaowei 
  6.  * @date 2014-3-30 下午12:22:08 
  7.  */  
  8. public class HighlighterParam {  
  9.     /**是否需要设置高亮*/  
  10.     private boolean highlight;  
  11.     /**需要设置高亮的属性名*/  
  12.     private String fieldName;  
  13.     /**高亮前缀*/  
  14.     private String prefix;  
  15.     /**高亮后缀*/  
  16.     private String stuffix;  
  17.     /**显示摘要最大长度*/  
  18.     private int fragmenterLength;  
  19.     public boolean isHighlight() {  
  20.         return highlight;  
  21.     }  
  22.     public void setHighlight(boolean highlight) {  
  23.         this.highlight = highlight;  
  24.     }  
  25.     public String getFieldName() {  
  26.         return fieldName;  
  27.     }  
  28.     public void setFieldName(String fieldName) {  
  29.         this.fieldName = fieldName;  
  30.     }  
  31.     public String getPrefix() {  
  32.         return prefix;  
  33.     }  
  34.     public void setPrefix(String prefix) {  
  35.         this.prefix = prefix;  
  36.     }  
  37.     public String getStuffix() {  
  38.         return stuffix;  
  39.     }  
  40.     public void setStuffix(String stuffix) {  
  41.         this.stuffix = stuffix;  
  42.     }  
  43.     public int getFragmenterLength() {  
  44.         return fragmenterLength;  
  45.     }  
  46.     public void setFragmenterLength(int fragmenterLength) {  
  47.         this.fragmenterLength = fragmenterLength;  
  48.     }  
  49.     public HighlighterParam(boolean highlight, String fieldName, String prefix, String stuffix, int fragmenterLength) {  
  50.         this.highlight = highlight;  
  51.         this.fieldName = fieldName;  
  52.         this.prefix = prefix;  
  53.         this.stuffix = stuffix;  
  54.         this.fragmenterLength = fragmenterLength;  
  55.     }  
  56.       
  57.     public HighlighterParam(boolean highlight, String fieldName, int fragmenterLength) {  
  58.         this.highlight = highlight;  
  59.         this.fieldName = fieldName;  
  60.         this.fragmenterLength = fragmenterLength;  
  61.     }  
  62.       
  63.     public HighlighterParam(boolean highlight, String fieldName, String prefix, String stuffix) {  
  64.         this.highlight = highlight;  
  65.         this.fieldName = fieldName;  
  66.         this.prefix = prefix;  
  67.         this.stuffix = stuffix;  
  68.     }  
  69.     public HighlighterParam() {  
  70.     }  
  71. }  

    工具类对IndexWriter,IndexReader,IndexSearcher,Analyzer,QueryParser等Lucene这些常用操作对象的获取进行了封装,其中IndexWriter采用了单例模式,确保始终只有一个对象实例,因为Lucene限制了索引写操作是阻塞的,即同一时刻只能有一个IndexWriter在执行写操作,直到indexWriter释放lock,而索引读的操作是可以并发进行的。如果你不想复制粘帖的话,请到最底下的附件里去下载源码。

    如果有哪里封装的不够合理,还望大家指正,多批评,谢谢!

 

    如果你还有什么问题请加我Q-Q:7-3-6-0-3-1-3-0-5,

或者加裙
一起交流学习!

转载:http://iamyida.iteye.com/blog/2196808

目录
相关文章
|
28天前
|
JavaScript 安全 Java
不要再封装各种Util工具类了,这个神级框架值得拥有
不要再封装各种Util工具类了,这个神级框架值得拥有
17 1
|
8月前
|
Java Python
HuTool工具类实用技巧:从常用方法入手
HuTool工具类实用技巧:从常用方法入手
170 0
|
9月前
|
SQL JSON Java
JavaOrm框架-基础文档
hyorm,一款自研java orm框架的使用方法
39 0
|
6月前
|
设计模式 前端开发 数据可视化
深入解析Java自定义MVC框架的原理与实现)
深入解析Java自定义MVC框架的原理与实现)
54 0
|
8月前
|
XML 存储 JavaScript
【JAVA基础】-JAVA开发中XML解析多种方法
【JAVA基础】-JAVA开发中XML解析多种方法
109 0
|
SQL JSON PHP
分享一下自己封装的Laravel常用工具类
分享一下自己封装的Laravel常用工具类
163 0
|
缓存 自然语言处理 安全
lucene原理及源码解析--核心类(下)
访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。具体到这个类就是不管是什么类型的数据,我都把它添加到Document对象里。
lucene原理及源码解析--核心类(下)
|
存储 设计模式 大数据
lucene原理及源码解析--核心类(上)
马云说:大家还没搞清PC时代的时候,移动互联网来了,还没搞清移动互联网的时候,大数据时代来了。 然而,我看到的是:在PC时代搞PC的,移动互联网时代搞移动互联网的,大数据时代搞大数据的,都是同一伙儿人。 我就是一个做业务方向的,而回忆起真正做技术的时光,也就是大数据时代刚来临的时候做搜索了。 搜索用的是solr框架,solr就是包装了lucene实现了近实时索引。所以源头还是lucene。而且lucene是java写的全文检索库,源码是一定要研究一下的。
lucene原理及源码解析--核心类(上)