`
m635674608
  • 浏览: 5028641 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

近实时搜索SearcherManager和NRTManager的使用

    博客分类:
  • java
 
阅读更多

lucene通过NRTManager这个类来实现近实时搜索,所谓近实时搜索即在索引发生改变时,通

过线程跟踪,在相对很短的时间反映给给用户程序的调用

NRTManager通过管理IndexWriter对象,并将IndexWriter的一些方法(增删改)例如

addDocument,deleteDocument等方法暴露给客户调用,它的操作全部在内存里面,所以如果

你不调用IndexWriter的commit方法,通过以上的操作,用户硬盘里面的索引库是不会变化的,所

以你每次更新完索引库请记得commit掉,这样才能将变化的索引一起写到硬盘中,实现索引更新后的同步
用户每次获取最新索引(IndexSearcher),可以通过两种方式,第一种是通过调用

NRTManagerReopenThread对象,该线程负责实时跟踪索引内存的变化,每次变化就调用

maybeReopen方法,保持最新代索引,打开一个新的IndexSearcher对象,而用户所要的

IndexSearcher对象是NRTManager通过调用getSearcherManager方法获得SearcherManager对

象,然后通过SearcherManager对象获取IndexSearcher对象返回个客户使用,用户使用完之

后调用SearcherManager的release释放IndexSearcher对象,最后记得关闭NRTManagerReopenThread;
第二种方式是不通过NRTManagerReopenThread对象,而是直接调用NRTManager的

maybeReopen方法来获取最新的IndexSearcher对象来获取最新索引

1、工程目录

2、只使用SearcherManager,不使用NRTManager的方式搜索

 

[java] view plaincopy
 
  1. package org.itat.index;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.util.concurrent.Executors;  
  6. import org.apache.lucene.analysis.Analyzer;  
  7. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  8. import org.apache.lucene.document.Document;  
  9. import org.apache.lucene.document.Field;  
  10. import org.apache.lucene.document.NumericField;  
  11. import org.apache.lucene.index.CorruptIndexException;  
  12. import org.apache.lucene.index.IndexReader;  
  13. import org.apache.lucene.index.IndexWriter;  
  14. import org.apache.lucene.index.IndexWriterConfig;  
  15. import org.apache.lucene.index.Term;  
  16. import org.apache.lucene.search.IndexSearcher;  
  17. import org.apache.lucene.search.ScoreDoc;  
  18. import org.apache.lucene.search.SearcherManager;  
  19. import org.apache.lucene.search.SearcherWarmer;  
  20. import org.apache.lucene.search.TermQuery;  
  21. import org.apache.lucene.search.TopDocs;  
  22. import org.apache.lucene.store.Directory;  
  23. import org.apache.lucene.store.FSDirectory;  
  24. import org.apache.lucene.store.LockObtainFailedException;  
  25. import org.apache.lucene.util.Version;  
  26.   
  27. /** 
  28.  * 只使用SearcherManager,不使用NRTManager 
  29.  *  
  30.  * SearcherManager的maybeReopen会自动检查是否需要重新打开,比如重复执行search02几次, 
  31.  * 中间的一次删除一条数据这个删除的数据需要对writer进行commit才行,这样硬盘上的索引才会生效 
  32.  * 那么使用maybeReopen就可以检测到硬盘中的索引是否改变,并在下次查询的时候就进行生效 
  33.  *  
  34.  * 但是: 
  35.  * 光使用SearcherManager的话做不到实时搜索,为什么呢? 
  36.  * 因为使用SearcherManager需要进行writer.commit才会检测到,但是我们知道writer的commit是非常 
  37.  * 消耗性能的,我们不能经常性的commit,那需要怎么做呢? 
  38.  * 我们只能把添加修改删除的操作在内存中生效,然后使用内存中的索引信息并且在搜索时能起到效果, 
  39.  * 过一段时间累计到一定程序才进行writer.commit 
  40.  */  
  41. public class IndexUtil1 {  
  42.     private String[] ids = {"1","2","3","4","5","6"};  
  43.     private String[] emails = {"aa@itat.org","bb@itat.org","cc@cc.org","dd@sina.org","ee@zttc.edu","ff@itat.org"};  
  44.     private String[] contents = {  
  45.             "welcome to visited the space,I like book",  
  46.             "hello boy, I like pingpeng ball",  
  47.             "my name is cc I like game",  
  48.             "I like football",  
  49.             "I like football and I like basketball too",  
  50.             "I like movie and swim"  
  51.     };  
  52.     private int[] attachs = {2,3,1,4,5,5};  
  53.     private String[] names = {"zhangsan","lisi","john","jetty","mike","jake"};  
  54.     private Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);  
  55.     private SearcherManager mgr = null;//是线程安全的  
  56.       
  57.     private Directory directory = null;  
  58.       
  59.     public IndexUtil1() {  
  60.         try {  
  61.             directory = FSDirectory.open(new File("D:\\Workspaces\\realtime\\index"));  
  62.             mgr = new SearcherManager(  
  63.                 directory,   
  64.                 new SearcherWarmer() {  
  65.                 /** 
  66.                  * 索引一更新就要重新获取searcher,那获取searcher的时候就会调用这个方法 
  67.                  * 执行maybeReopen的时候会执行warm方法,在这里可以对资源等进行控制 
  68.                  */  
  69.                     @Override  
  70.                     public void warm(IndexSearcher search) throws IOException {  
  71.                         System.out.println("has change");  
  72.                     }  
  73.                 },   
  74.                 Executors.newCachedThreadPool()  
  75.             );  
  76.         } catch (IOException e) {  
  77.             e.printStackTrace();  
  78.         }  
  79.     }  
  80.       
  81.     /** 
  82.      * 删除索引数据,默认不会完全删除,被放入索引回收站 
  83.      */  
  84.     public void delete(String id) {  
  85.         IndexWriter writer = null;  
  86.           
  87.         try {  
  88.             writer = new IndexWriter(directory,  
  89.                     new IndexWriterConfig(Version.LUCENE_35,analyzer));  
  90.             //参数是一个选项,可以是一个Query,也可以是一个term,term是一个精确查找的值  
  91.             //此时删除的文档并不会被完全删除,而是存储在一个回收站中的,可以恢复  
  92.             //执行完这个操作,索引文件夹下就会多出一个名叫_0_1.del的文件,也就是删除的文件在这个文件中记录了  
  93.             writer.deleteDocuments(new Term("id",id));  
  94.             writer.commit();  
  95.         } catch (CorruptIndexException e) {  
  96.             e.printStackTrace();  
  97.         } catch (LockObtainFailedException e) {  
  98.             e.printStackTrace();  
  99.         } catch (IOException e) {  
  100.             e.printStackTrace();  
  101.         } finally {  
  102.             try {  
  103.                 if(writer!=null) writer.close();  
  104.             } catch (CorruptIndexException e) {  
  105.                 e.printStackTrace();  
  106.             } catch (IOException e) {  
  107.                 e.printStackTrace();  
  108.             }  
  109.         }  
  110.     }  
  111.   
  112.     public void query() {  
  113.         try {  
  114.             IndexReader reader = IndexReader.open(directory);  
  115.             //通过reader可以有效的获取到文档的数量  
  116.             System.out.println("numDocs:"+reader.numDocs());//存储的文档数//不包括被删除的  
  117.             System.out.println("maxDocs:"+reader.maxDoc());//总存储量,包括在回收站中的索引  
  118.             System.out.println("deleteDocs:"+reader.numDeletedDocs());  
  119.             reader.close();  
  120.         } catch (CorruptIndexException e) {  
  121.             e.printStackTrace();  
  122.         } catch (IOException e) {  
  123.             e.printStackTrace();  
  124.         }  
  125.     }  
  126.     /** 
  127.      *  索引文件后缀为.fmn为保存的是域的名称等 
  128.      * .fdt和.fdx保存的是Store.YES的信息,保存域里面存储的数据 
  129.      * .frq表示这里的域哪些出现多少次,哪些单词出现多少次, 
  130.      * .nrm存储一些评分信息 
  131.      * .prx存储一些偏移量等 
  132.      * .tii和.tis专门存储索引里面的所有内容信息 
  133.      */  
  134.     public void index() {  
  135.         IndexWriter writer = null;  
  136.         try {  
  137.             //在2.9版本之后,lucene的就不是全部的索引格式都兼容的了,所以在使用的时候必须写明版本号  
  138.             writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, analyzer));  
  139.             writer.deleteAll();//清空索引  
  140.             Document doc = null;  
  141.             for(int i=0;i<ids.length;i++) {  
  142.                 doc = new Document();  
  143.                 doc.add(new Field("id",ids[i],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));  
  144.                 doc.add(new Field("email",emails[i],Field.Store.YES,Field.Index.NOT_ANALYZED));  
  145.                 doc.add(new Field("email","test"+i+"@test.com",Field.Store.YES,Field.Index.NOT_ANALYZED));  
  146.                 doc.add(new Field("content",contents[i],Field.Store.NO,Field.Index.ANALYZED));  
  147.                 doc.add(new Field("name",names[i],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));  
  148.                 //存储数字  
  149.                 //NumberTools.stringToLong("");已经被标记为过时了  
  150.                 doc.add(new NumericField("attach",Field.Store.YES,true).setIntValue(attachs[i]));  
  151.                 String et = emails[i].substring(emails[i].lastIndexOf("@")+1);  
  152.                 writer.addDocument(doc);  
  153.             }  
  154.         } catch (CorruptIndexException e) {  
  155.             e.printStackTrace();  
  156.         } catch (LockObtainFailedException e) {  
  157.             e.printStackTrace();  
  158.         } catch (IOException e) {  
  159.             e.printStackTrace();  
  160.         } finally {  
  161.             try {  
  162.                 if(writer!=null)writer.close();  
  163.             } catch (CorruptIndexException e) {  
  164.                 e.printStackTrace();  
  165.             } catch (IOException e) {  
  166.                 e.printStackTrace();  
  167.             }  
  168.         }  
  169.     }  
  170.       
  171.     public void search02() {  
  172.         IndexSearcher searcher = mgr.acquire();//获得一个searcher  
  173.         try {  
  174.             /** 
  175.              * maybeReopen会自动检查是否需要重新打开 
  176.              * 比如重复执行search02几次,中间一次删除一条数据 
  177.              * 这个删除的数据需要对writer进行commit才行 
  178.              * 那么使用maybeReopen就可以检测到硬盘中的索引是否改变 
  179.              * 并在下次查询的时候把删除的这条给去掉 
  180.              */  
  181.             mgr.maybeReopen();  
  182.             TermQuery query = new TermQuery(new Term("content","like"));  
  183.             TopDocs tds = searcher.search(query, 10);  
  184.             for(ScoreDoc sd:tds.scoreDocs) {  
  185.                 Document doc = searcher.doc(sd.doc);  
  186.                 System.out.println(doc.get("id")+"---->"+  
  187.                         doc.get("name")+"["+doc.get("email")+"]-->"+doc.get("id")+","+  
  188.                         doc.get("attach")+","+doc.get("date")+","+doc.getValues("email")[1]);  
  189.             }  
  190.             searcher.close();  
  191.         } catch (CorruptIndexException e) {  
  192.             e.printStackTrace();  
  193.         } catch (IOException e) {  
  194.             e.printStackTrace();  
  195.         } finally{  
  196.             try {  
  197.                 mgr.release(searcher);//释放一个searcher  
  198.             } catch (IOException e) {  
  199.                 e.printStackTrace();  
  200.             }  
  201.         }  
  202.     }  
  203.   
  204. }  


3、SearcherManager和NRTManager联合使用

 

 

[java] view plaincopy
 
  1. package org.itat.index;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import org.apache.lucene.analysis.Analyzer;  
  6. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  7. import org.apache.lucene.document.Document;  
  8. import org.apache.lucene.document.Field;  
  9. import org.apache.lucene.document.NumericField;  
  10. import org.apache.lucene.index.CorruptIndexException;  
  11. import org.apache.lucene.index.IndexReader;  
  12. import org.apache.lucene.index.IndexWriter;  
  13. import org.apache.lucene.index.IndexWriterConfig;  
  14. import org.apache.lucene.index.Term;  
  15. import org.apache.lucene.search.IndexSearcher;  
  16. import org.apache.lucene.search.NRTManager;  
  17. import org.apache.lucene.search.NRTManagerReopenThread;  
  18. import org.apache.lucene.search.ScoreDoc;  
  19. import org.apache.lucene.search.SearcherManager;  
  20. import org.apache.lucene.search.SearcherWarmer;  
  21. import org.apache.lucene.search.TermQuery;  
  22. import org.apache.lucene.search.TopDocs;  
  23. import org.apache.lucene.store.Directory;  
  24. import org.apache.lucene.store.FSDirectory;  
  25. import org.apache.lucene.store.LockObtainFailedException;  
  26. import org.apache.lucene.util.Version;  
  27.   
  28. /** 
  29.  * SearcherManager和NRTManager联合使用 
  30.  *  
  31.  * SearcherManager的maybeReopen会自动检查是否需要重新打开,比如重复执行search02几次, 
  32.  * 中间的一次删除一条数据这个删除的数据需要对writer进行commit才行,这样硬盘上的索引才会生效 
  33.  * 那么使用maybeReopen就可以检测到硬盘中的索引是否改变,并在下次查询的时候就进行生效 
  34.  *  
  35.  * 但是: 
  36.  * 光使用SearcherManager的话做不到实时搜索,为什么呢? 
  37.  * 因为使用SearcherManager需要进行writer.commit才会检测到,但是我们知道writer的commit是非常 
  38.  * 消耗性能的,我们不能经常性的commit,那需要怎么做呢? 
  39.  * 我们只能把添加修改删除的操作在内存中生效,然后使用内存中的索引信息并且在搜索时能起到效果, 
  40.  * 过一段时间累计到一定程序才进行writer.commit 
  41.  * NRTManage就是这样的功能,把更新的数据存储在内容中,但是lucene搜索的时候也可以搜索到,需要 
  42.  * writer进行commit才会把索引更新到硬盘中 
  43.  */  
  44. public class IndexUtil2 {  
  45.     private String[] ids = {"1","2","3","4","5","6"};  
  46.     private String[] emails = {"aa@itat.org","bb@itat.org","cc@cc.org","dd@sina.org","ee@zttc.edu","ff@itat.org"};  
  47.     private String[] contents = {  
  48.             "welcome to visited the space,I like book",  
  49.             "hello boy, I like pingpeng ball",  
  50.             "my name is cc I like game",  
  51.             "I like football",  
  52.             "I like football and I like basketball too",  
  53.             "I like movie and swim"  
  54.     };  
  55.     private int[] attachs = {2,3,1,4,5,5};  
  56.     private String[] names = {"zhangsan","lisi","john","jetty","mike","jake"};  
  57.     private Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);  
  58.     private SearcherManager mgr = null;//是线程安全的  
  59.     private NRTManager nrtMgr = null;//near real time  近实时搜索  
  60.     private Directory directory = null;  
  61.     private IndexWriter writer = null;  
  62.       
  63.     public IndexUtil2() {  
  64.         try {  
  65.             directory = FSDirectory.open(new File("D:\\Workspaces\\realtime\\index"));  
  66.             writer = new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_35, analyzer));  
  67.             nrtMgr = new NRTManager(writer,   
  68.                         new SearcherWarmer() {  
  69.                             /** 
  70.                              * 索引一更新就要重新获取searcher,那获取searcher的时候就会调用这个方法 
  71.                              * 执行maybeReopen的时候会执行warm方法,在这里可以对资源等进行控制 
  72.                              */  
  73.                             @Override  
  74.                             public void warm(IndexSearcher search) throws IOException {  
  75.                                 System.out.println("has open");  
  76.                             }  
  77.                         }  
  78.             );  
  79.             //启动NRTManager的Reopen线程  
  80.             //NRTManagerReopenThread会每隔25秒去检测一下索引是否更新并判断是否需要重新打开writer  
  81.             NRTManagerReopenThread reopen = new NRTManagerReopenThread(nrtMgr, 5.00.025);//0.025为25秒  
  82.             reopen.setDaemon(true);//设为后台线程  
  83.             reopen.setName("NrtManager Reopen Thread");  
  84.             reopen.start();  
  85.               
  86.             mgr = nrtMgr.getSearcherManager(true);//true为允许所有的更新  
  87.         } catch (IOException e) {  
  88.             e.printStackTrace();  
  89.         }  
  90.     }  
  91.       
  92.     /** 
  93.      * 删除索引数据,默认不会完全删除,被放入索引回收站 
  94.      */  
  95.     public void delete(String id) {  
  96.           
  97.         try {  
  98.             //参数是一个选项,可以是一个Query,也可以是一个term,term是一个精确查找的值  
  99.             //此时删除的文档并不会被完全删除,而是存储在一个回收站中的,可以恢复  
  100.             //执行完这个操作,索引文件夹下就会多出一个名叫_0_1.del的文件,也就是删除的文件在这个文件中记录了  
  101.             nrtMgr.deleteDocuments(new Term("id",id));//使用使用nrtMgr来删除  
  102.         } catch (CorruptIndexException e) {  
  103.             e.printStackTrace();  
  104.         } catch (LockObtainFailedException e) {  
  105.             e.printStackTrace();  
  106.         } catch (IOException e) {  
  107.             e.printStackTrace();  
  108.         }   
  109.     }  
  110.   
  111.     public void query() {  
  112.         try {  
  113.             IndexReader reader = IndexReader.open(directory);  
  114.             //通过reader可以有效的获取到文档的数量  
  115.             System.out.println("numDocs:"+reader.numDocs());//存储的文档数//不包括被删除的  
  116.             System.out.println("maxDocs:"+reader.maxDoc());//总存储量,包括在回收站中的索引  
  117.             System.out.println("deleteDocs:"+reader.numDeletedDocs());  
  118.             reader.close();  
  119.         } catch (CorruptIndexException e) {  
  120.             e.printStackTrace();  
  121.         } catch (IOException e) {  
  122.             e.printStackTrace();  
  123.         }  
  124.     }  
  125.     /** 
  126.      *  索引文件后缀为.fmn为保存的是域的名称等 
  127.      * .fdt和.fdx保存的是Store.YES的信息,保存域里面存储的数据 
  128.      * .frq表示这里的域哪些出现多少次,哪些单词出现多少次, 
  129.      * .nrm存储一些评分信息 
  130.      * .prx存储一些偏移量等 
  131.      * .tii和.tis专门存储索引里面的所有内容信息 
  132.      */  
  133.     public void index() {  
  134.         IndexWriter writer = null;  
  135.         try {  
  136.             //在2.9版本之后,lucene的就不是全部的索引格式都兼容的了,所以在使用的时候必须写明版本号  
  137.             writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, analyzer));  
  138.             writer.deleteAll();//清空索引  
  139.             Document doc = null;  
  140.             for(int i=0;i<ids.length;i++) {  
  141.                 doc = new Document();  
  142.                 doc.add(new Field("id",ids[i],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));  
  143.                 doc.add(new Field("email",emails[i],Field.Store.YES,Field.Index.NOT_ANALYZED));  
  144.                 doc.add(new Field("email","test"+i+"@test.com",Field.Store.YES,Field.Index.NOT_ANALYZED));  
  145.                 doc.add(new Field("content",contents[i],Field.Store.NO,Field.Index.ANALYZED));  
  146.                 doc.add(new Field("name",names[i],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));  
  147.                 //存储数字  
  148.                 //NumberTools.stringToLong("");已经被标记为过时了  
  149.                 doc.add(new NumericField("attach",Field.Store.YES,true).setIntValue(attachs[i]));  
  150.                 String et = emails[i].substring(emails[i].lastIndexOf("@")+1);  
  151.                 writer.addDocument(doc);  
  152.             }  
  153.         } catch (CorruptIndexException e) {  
  154.             e.printStackTrace();  
  155.         } catch (LockObtainFailedException e) {  
  156.             e.printStackTrace();  
  157.         } catch (IOException e) {  
  158.             e.printStackTrace();  
  159.         } finally {  
  160.             try {  
  161.                 if(writer!=null)writer.close();  
  162.             } catch (CorruptIndexException e) {  
  163.                 e.printStackTrace();  
  164.             } catch (IOException e) {  
  165.                 e.printStackTrace();  
  166.             }  
  167.         }  
  168.     }  
  169.       
  170.     public void search02() {  
  171.         IndexSearcher searcher = mgr.acquire();//获得一个searcher  
  172.         try {  
  173.             /** 
  174.              * maybeReopen会自动检查是否需要重新打开 
  175.              * 比如重复执行search02几次,中间一次删除一条数据 
  176.              * 这个删除的数据需要对writer进行commit才行 
  177.              * 那么使用maybeReopen就可以检测到硬盘中的索引是否改变 
  178.              * 并在下次查询的时候把删除的这条给去掉 
  179.              */  
  180.             TermQuery query = new TermQuery(new Term("content","like"));  
  181.             TopDocs tds = searcher.search(query, 10);  
  182.             for(ScoreDoc sd:tds.scoreDocs) {  
  183.                 Document doc = searcher.doc(sd.doc);  
  184.                 System.out.println(doc.get("id")+"---->"+  
  185.                         doc.get("name")+"["+doc.get("email")+"]-->"+doc.get("id")+","+  
  186.                         doc.get("attach")+","+doc.get("date")+","+doc.getValues("email")[1]);  
  187.             }  
  188.             searcher.close();  
  189.         } catch (CorruptIndexException e) {  
  190.             e.printStackTrace();  
  191.         } catch (IOException e) {  
  192.             e.printStackTrace();  
  193.         } finally{  
  194.             try {  
  195.                 mgr.release(searcher);//释放一个searcher  
  196.             } catch (IOException e) {  
  197.                 e.printStackTrace();  
  198.             }  
  199.         }  
  200.     }  
  201.   
  202. }  

4、不使用SearcherManager和NRTManager

 

[java] view plaincopy
 
  1. package org.itat.index;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  6. import org.apache.lucene.document.Document;  
  7. import org.apache.lucene.document.Field;  
  8. import org.apache.lucene.document.NumericField;  
  9. import org.apache.lucene.index.CorruptIndexException;  
  10. import org.apache.lucene.index.IndexReader;  
  11. import org.apache.lucene.index.IndexWriter;  
  12. import org.apache.lucene.index.IndexWriterConfig;  
  13. import org.apache.lucene.index.Term;  
  14. import org.apache.lucene.search.IndexSearcher;  
  15. import org.apache.lucene.search.ScoreDoc;  
  16. import org.apache.lucene.search.TermQuery;  
  17. import org.apache.lucene.search.TopDocs;  
  18. import org.apache.lucene.store.Directory;  
  19. import org.apache.lucene.store.FSDirectory;  
  20. import org.apache.lucene.store.LockObtainFailedException;  
  21. import org.apache.lucene.util.Version;  
  22.   
  23. /** 
  24.  * 不使用SearcherManager和NRTManager 
  25.  * @author user 
  26.  */  
  27. public class IndexUtil {  
  28.     private String[] ids = {"1","2","3","4","5","6"};  
  29.     private String[] emails = {"aa@itat.org","bb@itat.org","cc@cc.org","dd@sina.org","ee@zttc.edu","ff@itat.org"};  
  30.     private String[] contents = {  
  31.             "welcome to visited the space,I like book",  
  32.             "hello boy, I like pingpeng ball",  
  33.             "my name is cc I like game",  
  34.             "I like football",  
  35.             "I like football and I like basketball too",  
  36.             "I like movie and swim"  
  37.     };  
  38.     private int[] attachs = {2,3,1,4,5,5};  
  39.     private String[] names = {"zhangsan","lisi","john","jetty","mike","jake"};  
  40.       
  41.     private Directory directory = null;  
  42.     private static IndexReader reader = null;  
  43.       
  44.     public IndexUtil() {  
  45.         try {  
  46.             directory = FSDirectory.open(new File("D:\\Workspaces\\realtime\\index"));  
  47. //          directory = new RAMDirectory();  
  48. //          index();  
  49.             reader = IndexReader.open(directory,false);  
  50.         } catch (IOException e) {  
  51.             e.printStackTrace();  
  52.         }  
  53.     }  
  54.       
  55.     /** 
  56.      * 对于IndexReader而言,反复使用Index.open打开会有很大的开销,所以一般在整个程序的生命周期中 
  57.      * 只会打开一个IndexReader,通过这个IndexReader来创建不同的IndexSearcher,如果使用单例模式, 
  58.      * 可能出现的问题有: 
  59.      * 1、当使用Writer修改了索引之后不会更新信息,所以需要使用IndexReader.openIfChange方法操作 
  60.      * 如果IndexWriter在创建完成之后,没有关闭,需要进行commit操作之后才能提交 
  61.      * @return 
  62.      */  
  63.     public IndexSearcher getSearcher() {  
  64.         try {  
  65.             if(reader==null) {  
  66.                 reader = IndexReader.open(directory,false);  
  67.             } else {  
  68.                 IndexReader tr = IndexReader.openIfChanged(reader);  
  69.                 //如果原来的reader没改变,返回null  
  70.                 //如果原来的reader改变,则更新为新的索引  
  71.                 if(tr!=null) {  
  72.                     reader.close();  
  73.                     reader = tr;  
  74.                 }  
  75.             }  
  76.             return new IndexSearcher(reader);  
  77.         } catch (CorruptIndexException e) {  
  78.             e.printStackTrace();  
  79.         } catch (IOException e) {  
  80.             e.printStackTrace();  
  81.         }  
  82.         return null;  
  83.           
  84.     }  
  85.   
  86.     /** 
  87.      * 删除索引数据,默认不会完全删除,被放入索引回收站 
  88.      */  
  89.     public void delete() {  
  90.         IndexWriter writer = null;  
  91.           
  92.         try {  
  93.             writer = new IndexWriter(directory,  
  94.                     new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35)));  
  95.             //参数是一个选项,可以是一个Query,也可以是一个term,term是一个精确查找的值  
  96.             //此时删除的文档并不会被完全删除,而是存储在一个回收站中的,可以恢复  
  97.             //执行完这个操作,索引文件夹下就会多出一个名叫_0_1.del的文件,也就是删除的文件在这个文件中记录了  
  98.             writer.deleteDocuments(new Term("id","1"));  
  99.             writer.commit();  
  100.         } catch (CorruptIndexException e) {  
  101.             e.printStackTrace();  
  102.         } catch (LockObtainFailedException e) {  
  103.             e.printStackTrace();  
  104.         } catch (IOException e) {  
  105.             e.printStackTrace();  
  106.         } finally {  
  107.             try {  
  108.                 if(writer!=null) writer.close();  
  109.             } catch (CorruptIndexException e) {  
  110.                 e.printStackTrace();  
  111.             } catch (IOException e) {  
  112.                 e.printStackTrace();  
  113.             }  
  114.         }  
  115.     }  
  116.   
  117.       
  118.     public void query() {  
  119.         try {  
  120.             IndexReader reader = IndexReader.open(directory);  
  121.             //通过reader可以有效的获取到文档的数量  
  122.             System.out.println("numDocs:"+reader.numDocs());//存储的文档数//不包括被删除的  
  123.             System.out.println("maxDocs:"+reader.maxDoc());//总存储量,包括在回收站中的索引  
  124.             System.out.println("deleteDocs:"+reader.numDeletedDocs());  
  125.             reader.close();  
  126.         } catch (CorruptIndexException e) {  
  127.             e.printStackTrace();  
  128.         } catch (IOException e) {  
  129.             e.printStackTrace();  
  130.         }  
  131.     }  
  132.     /** 
  133.      *  索引文件后缀为.fmn为保存的是域的名称等 
  134.      * .fdt和.fdx保存的是Store.YES的信息,保存域里面存储的数据 
  135.      * .frq表示这里的域哪些出现多少次,哪些单词出现多少次, 
  136.      * .nrm存储一些评分信息 
  137.      * .prx存储一些偏移量等 
  138.      * .tii和.tis专门存储索引里面的所有内容信息 
  139.      */  
  140.     public void index() {  
  141.         IndexWriter writer = null;  
  142.         try {  
  143.             //在2.9版本之后,lucene的就不是全部的索引格式都兼容的了,所以在使用的时候必须写明版本号  
  144.             writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));  
  145.             writer.deleteAll();//清空索引  
  146.             Document doc = null;  
  147.             for(int i=0;i<ids.length;i++) {  
  148.                 doc = new Document();  
  149.                 doc.add(new Field("id",ids[i],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));  
  150.                 doc.add(new Field("email",emails[i],Field.Store.YES,Field.Index.NOT_ANALYZED));  
  151.                 doc.add(new Field("email","test"+i+"@test.com",Field.Store.YES,Field.Index.NOT_ANALYZED));  
  152.                 doc.add(new Field("content",contents[i],Field.Store.NO,Field.Index.ANALYZED));  
  153.                 doc.add(new Field("name",names[i],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));  
  154.                 //存储数字  
  155.                 //NumberTools.stringToLong("");已经被标记为过时了  
  156.                 doc.add(new NumericField("attach",Field.Store.YES,true).setIntValue(attachs[i]));  
  157.                 String et = emails[i].substring(emails[i].lastIndexOf("@")+1);  
  158.                 writer.addDocument(doc);  
  159.             }  
  160.         } catch (CorruptIndexException e) {  
  161.             e.printStackTrace();  
  162.         } catch (LockObtainFailedException e) {  
  163.             e.printStackTrace();  
  164.         } catch (IOException e) {  
  165.             e.printStackTrace();  
  166.         } finally {  
  167.             try {  
  168.                 if(writer!=null)writer.close();  
  169.             } catch (CorruptIndexException e) {  
  170.                 e.printStackTrace();  
  171.             } catch (IOException e) {  
  172.                 e.printStackTrace();  
  173.             }  
  174.         }  
  175.     }  
  176.   
  177.     public void search02() {  
  178.         try {  
  179.             IndexSearcher searcher = getSearcher();  
  180.             TermQuery query = new TermQuery(new Term("content","like"));  
  181.             TopDocs tds = searcher.search(query, 10);  
  182.             for(ScoreDoc sd:tds.scoreDocs) {  
  183.                 Document doc = searcher.doc(sd.doc);  
  184.                 System.out.println(doc.get("id")+"---->"+  
  185.                         doc.get("name")+"["+doc.get("email")+"]-->"+doc.get("id")+","+  
  186.                         doc.get("attach")+","+doc.get("date")+","+doc.getValues("email")[1]);  
  187.             }  
  188.             searcher.close();  
  189.         } catch (CorruptIndexException e) {  
  190.             e.printStackTrace();  
  191.         } catch (IOException e) {  
  192.             e.printStackTrace();  
  193.         }  
  194.     }  
  195.   
  196. }  

 

工程路径:http://download.csdn.net/detail/wxwzy738/5332972

 

http://my.oschina.net/tianshibuzuoai/blog/65271

http://blog.csdn.net/wxwzy738/article/details/8886920

 

相当于jdbc的连接池。

 

 

分享到:
评论

相关推荐

    近实时搜索SearcherManager

    本文将详细探讨近实时搜索的原理以及如何使用SearcherManager和NRTManager来实现在Lucene中的应用。 近实时搜索的基本思想是通过快速地刷新索引,使得新添加或者更新的数据能够尽快被搜索到。在传统的全文搜索引擎...

    NrtManager:来自 Lucene 3.5.0 的 NrtManager 和 SearcherManager 的 C# 端口

    Java版本的Lucene 3.5.0引入了NrtManager和SearcherManager两个关键组件,它们对于实时搜索和索引更新有着重要作用。本文将详细介绍这两个组件,并探讨其在C#端的移植过程和应用场景。 首先,NrtManager(Near Real...

    使用C sharp开发搜索引擎 C#搜索引擎开发实战 29-搜索界面(共12页).ppt

    本课程主要讲解了如何设计和实现这样的界面,包括缓存索引、翻页功能以及将搜索结果与具体应用相结合。 首先,缓存索引是提高搜索效率的关键。由于打开大型索引文件(如几百MB以上)可能耗费较长时间,因此采用`...

    一步一步跟我学习lucene(12)---lucene搜索之分组处理group查询

    1. **配置搜索器**:在建立搜索器时,我们需要使用支持分组的`SearcherManager`,例如`TopGroupsSearcher`。这将确保我们的搜索请求能够处理分组。 2. **创建分组策略**:我们需要定义一个`GroupingCollector`,它...

    Lucene 常用功能介绍视频详解

    6. **近实时搜索** 通过NRT(Near Real Time)机制,Lucene能够迅速反映索引的最新变化。即使在索引过程中,用户也可以通过`IndexReader`和`SearcherManager`获取到最新的搜索结果。 7. **多字段搜索** Lucene...

    LuceneUtils_lucenejava_全文检索_lucene_

    此外,还可以通过自定义`Filter`、`Tokenizer`和`TokenStream`对文本分析进行深度定制,满足特定的索引和搜索需求。 总结,LuceneJava为开发者提供了构建全文检索系统所需的一切工具。通过理解并熟练运用其创建索引...

    详解SpringBoot+Lucene案例介绍

    * IndexSearcher需要通过SearcherManager管理,因为IndexSearcher如果初始化的时候加载了索引文件夹,那么后面添加、删除、修改的索引都不能通过IndexSearcher查出来,因为它没有与索引库实时同步。 * 我们需要创建...

    lucence 测试代码可运行

    1. **创建SearcherManager**:`SearcherManager`管理着对索引的搜索,提供了在更新索引时的线程安全搜索。 2. **创建QueryParser**:使用`QueryParser`解析用户输入的查询字符串,生成`Query`对象。 3. **执行查询...

    Lucene3.5的学习研究报告

    SearcherManager的加入是为了解决多线程搜索中的管理问题,它使得跨多个搜索线程的IndexSearchers共享和重新启动变得更加简便。同时,SearcherLifetimeManager确保在跨多个请求(如分页或下钻查询)时提供一致的索引...

    Lucene 原理与代码分析完整版.pdf

    - **SearcherManager**:管理IndexReader的生命周期,提供搜索功能。 ### 索引文件格式 Lucene的索引文件采用了一种高效的存储格式,旨在最小化磁盘空间占用并加速数据访问。关键特性包括: - **前缀后缀规则**:...

    lucene原理与代码分析完整版

    - **合并操作**:将多个小段合并成一个大段,以提高搜索效率和降低磁盘占用。 **2. 段合并的详细过程** - **选择合并**:根据合并策略选择需要合并的段。 - **将缓存写入新的段**:将未写入磁盘的临时数据写入新...

Global site tag (gtag.js) - Google Analytics