【Lucene3.6.2入门系列】第07节_高级搜索之普通Filter和自定义Filter

本文详细介绍了如何使用Lucene3.6.2进行高级搜索,包括普通Filter和自定义Filter的使用方法。通过示例展示了如何根据文件大小、文件名、文件内容、文件日期等条件进行过滤搜索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[java]  view plain copy print ?
  1. package com.jadyer.lucene;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.text.ParseException;  
  6. import java.text.SimpleDateFormat;  
  7. import java.util.Date;  
  8.   
  9. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  10. import org.apache.lucene.document.Document;  
  11. import org.apache.lucene.document.Field;  
  12. import org.apache.lucene.document.NumericField;  
  13. import org.apache.lucene.index.IndexReader;  
  14. import org.apache.lucene.index.IndexWriter;  
  15. import org.apache.lucene.index.IndexWriterConfig;  
  16. import org.apache.lucene.queryParser.QueryParser;  
  17. import org.apache.lucene.search.Filter;  
  18. import org.apache.lucene.search.IndexSearcher;  
  19. import org.apache.lucene.search.ScoreDoc;  
  20. import org.apache.lucene.search.TopDocs;  
  21. import org.apache.lucene.store.Directory;  
  22. import org.apache.lucene.store.FSDirectory;  
  23. import org.apache.lucene.util.Version;  
  24.   
  25. import com.jadyer.custom.MyFilter;  
  26.   
  27. /** 
  28.  * 【Lucene3.6.2入门系列】第07节_高级搜索之普通Filter和自定义Filter 
  29.  * @create Aug 19, 2013 11:13:40 AM 
  30.  * @author 玄玉<http://blog.youkuaiyun.com/jadyer> 
  31.  */  
  32. public class AdvancedSearchByFilter {  
  33.     private Directory directory;  
  34.     private IndexReader reader;  
  35.       
  36.     public AdvancedSearchByFilter(){  
  37.         /**文件大小*/  
  38.         int[] sizes = {901020106050};  
  39.         /**文件名*/  
  40.         String[] names = {"Michael.java""Scofield.ini""Tbag.txt""Jack""Jade""Jadyer"};  
  41.         /**文件内容*/  
  42.         String[] contents = {"my java blog is http://blog.youkuaiyun.com/jadyer",  
  43.                              "my Java Website is http://www.jadyer.cn",  
  44.                              "my name is jadyer",  
  45.                              "I am a Java Developer",  
  46.                              "I am from Haerbin",  
  47.                              "I like java of Lucene"};  
  48.         /**文件日期*/  
  49.         Date[] dates = new Date[sizes.length];  
  50.         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss");  
  51.         IndexWriter writer = null;  
  52.         Document doc = null;  
  53.         try {  
  54.             dates[0] = sdf.parse("20130407 15:25:30");  
  55.             dates[1] = sdf.parse("20130407 16:30:45");  
  56.             dates[2] = sdf.parse("20130213 11:15:25");  
  57.             dates[3] = sdf.parse("20130808 09:30:55");  
  58.             dates[4] = sdf.parse("20130526 13:54:22");  
  59.             dates[5] = sdf.parse("20130701 17:35:34");  
  60.             directory = FSDirectory.open(new File("myExample/01_index/"));  
  61.             writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_36, new StandardAnalyzer(Version.LUCENE_36)));  
  62.             writer.deleteAll();  
  63.             for(int i=0; i<sizes.length; i++){  
  64.                 doc = new Document();  
  65.                 doc.add(new NumericField("size",Field.Store.YES, true).setIntValue(sizes[i]));  
  66.                 doc.add(new Field("name", names[i], Field.Store.YES, Field.Index.ANALYZED_NO_NORMS));  
  67.                 doc.add(new Field("content", contents[i], Field.Store.NO, Field.Index.ANALYZED));  
  68.                 doc.add(new NumericField("date", Field.Store.YES, true).setLongValue(dates[i].getTime()));  
  69.                 //为每个文档添加一个fileID(与ScoreDoc.doc不同),专门在自定义Filter时使用  
  70.                 doc.add(new Field("fileID", String.valueOf(i), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));  
  71.                 writer.addDocument(doc);  
  72.             }  
  73.         } catch (Exception e) {  
  74.             e.printStackTrace();  
  75.         } finally {  
  76.             if(null != writer){  
  77.                 try {  
  78.                     writer.close();  
  79.                 } catch (IOException ce) {  
  80.                     ce.printStackTrace();  
  81.                 }  
  82.             }  
  83.         }  
  84.     }  
  85.       
  86.     /** 
  87.      * 获取IndexReader实例 
  88.      */  
  89.     private IndexReader getIndexReader(){  
  90.         try {  
  91.             if(reader == null){  
  92.                 reader = IndexReader.open(directory);  
  93.             }else{  
  94.                 //if the index was changed since the provided reader was opened, open and return a new reader; else,return null  
  95.                 //如果当前reader在打开期间index发生改变,则打开并返回一个新的IndexReader,否则返回null  
  96.                 IndexReader ir = IndexReader.openIfChanged(reader);  
  97.                 if(ir != null){  
  98.                     reader.close(); //关闭原reader  
  99.                     reader = ir;    //赋予新reader  
  100.                 }  
  101.             }  
  102.             return reader;  
  103.         }catch(Exception e) {  
  104.             e.printStackTrace();  
  105.         }  
  106.         return null//发生异常则返回null  
  107.     }  
  108.       
  109.       
  110.     /** 
  111.      * 搜索过滤 
  112.      */  
  113.     public void searchByFilter(String expr, Filter filter){  
  114.         IndexSearcher searcher = new IndexSearcher(this.getIndexReader());  
  115.         QueryParser parser = new QueryParser(Version.LUCENE_36, "content"new StandardAnalyzer(Version.LUCENE_36));  
  116.         TopDocs tds = null;  
  117.         try {  
  118.             if(null == filter){  
  119.                 tds = searcher.search(parser.parse(expr), 10);  
  120.             }else{  
  121.                 tds = searcher.search(parser.parse(expr), filter, 10);  
  122.             }  
  123.             for(ScoreDoc sd : tds.scoreDocs){  
  124.                 Document doc = searcher.doc(sd.doc);  
  125.                 System.out.print("文档编号=" + sd.doc + "  文档权值=" + doc.getBoost() + "  文档评分=" + sd.score + "    ");  
  126.                 System.out.println("fileID=" + doc.get("fileID") + "  size=" + doc.get("size") + "  date=" + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date(Long.parseLong(doc.get("date")))) + "  name=" + doc.get("name"));  
  127.             }  
  128.         } catch (Exception e) {  
  129.             e.printStackTrace();  
  130.         } finally {  
  131.             if(searcher != null){  
  132.                 try {  
  133.                     searcher.close();  
  134.                 } catch (IOException e) {  
  135.                     e.printStackTrace();  
  136.                 }  
  137.             }  
  138.         }  
  139.     }  
  140.       
  141.       
  142.     /** 
  143.      * 测试一下过滤效果 
  144.      */  
  145.     public static void main(String[] args) throws ParseException {  
  146.         AdvancedSearchByFilter advancedSearch = new AdvancedSearchByFilter();  
  147. //      //过滤文件名首字母从'h'到'n'的记录(注意hn要小写)  
  148. //      advancedSearch.searchByFilter("Java", new TermRangeFilter("name", "h", "n", true, true));  
  149. //      //过滤文件大小在30到80以内的记录  
  150. //      advancedSearch.searchByFilter("Java", NumericRangeFilter.newIntRange("size", 30, 80, true, true));  
  151. //      //过滤文件日期在20130701 00:00:00到20130808 23:59:59之间的记录  
  152. //      Long min = Long.valueOf(new SimpleDateFormat("yyyyMMdd").parse("20130701").getTime());  
  153. //      Long max = Long.valueOf(new SimpleDateFormat("yyyyMMdd HH:mm:ss").parse("20130808 23:59:59").getTime());  
  154. //      advancedSearch.searchByFilter("Java", NumericRangeFilter.newLongRange("date", min, max, true, true));  
  155. //      //过滤文件名以'ja'打头的(注意ja要小写)  
  156. //      advancedSearch.searchByFilter("Java", new QueryWrapperFilter(new WildcardQuery(new Term("name", "ja*"))));  
  157.         //自定义Filter  
  158.         advancedSearch.searchByFilter("Java"new MyFilter());  
  159.     }  
  160. }  


下面是自定义的MyFilter.java

[java]  view plain copy print ?
  1. package com.jadyer.custom;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.apache.lucene.index.IndexReader;  
  6. import org.apache.lucene.index.Term;  
  7. import org.apache.lucene.index.TermDocs;  
  8. import org.apache.lucene.search.DocIdSet;  
  9. import org.apache.lucene.search.Filter;  
  10. import org.apache.lucene.util.OpenBitSet;  
  11.   
  12. /** 
  13.  * 自定义Filter 
  14.  * @see ------------------------------------------------------------------------------------------ 
  15.  * @see 本例的应用场景 
  16.  * @see 假设很多的数据,然后删除了其中的某几条数据,此时在接受搜索请求时为保证不会搜索到已删除的数据 
  17.  * @see 那么可以更新索引,但更新索引会消耗很多时间(因为数据量大),而又要保证已删除的数据不会被搜索到 
  18.  * @see 此时就可以自定义Filter,原理即搜索过程中,当发现此记录为已删除记录,则不添加到返回的搜索结果集中 
  19.  * @see ------------------------------------------------------------------------------------------ 
  20.  * @see 自定义Filter步骤如下 
  21.  * @see 1)继承Filter类并重写getDocIdSet()方法 
  22.  * @see 2)根据实际过滤要求返回新的DocIdSet对象 
  23.  * @see ------------------------------------------------------------------------------------------ 
  24.  * @see DocIdSet小解 
  25.  * @see 这里Filter干的活其实就是创建一个DocIdSet,而DocIdSet其实就是一个数组,可以理解为其中只存放0或1的值 
  26.  * @see 每个搜索出来的Document都有一个文档编号,所以搜索出来多少个Document,那么DocIdSet中就会有多少条记录 
  27.  * @see 而DocIdSet中每一条记录的索引号与文档编号是一一对应的 
  28.  * @see 所以当DocIdSet中的记录为1时,则对应文档编号的Document就会被添加到TopDocs中,为0就会被过滤掉 
  29.  * @see ------------------------------------------------------------------------------------------ 
  30.  * @create Aug 6, 2013 7:28:53 PM 
  31.  * @author 玄玉<http://blog.youkuaiyun.com/jadyer> 
  32.  */  
  33. public class MyFilter extends Filter {  
  34.     private static final long serialVersionUID = -8955061358165068L;  
  35.       
  36.     //假设这是已删除记录的fileID值的集合  
  37.     private String[] deleteFileIDs = {"1""3"};  
  38.       
  39.     @Override  
  40.     public DocIdSet getDocIdSet(IndexReader reader) throws IOException {  
  41.         //创建一个DocIdSet的子类OpenBitSet(创建之后默认所有元素都是0),传的参数就是本次"搜索到的"元素数目  
  42.         OpenBitSet obs = new OpenBitSet(reader.maxDoc());  
  43.         //先把元素填满,即全部设置为1  
  44.         obs.set(0, reader.maxDoc());  
  45.         //用于保存已删除元素的文档编号  
  46.         int[] docs = new int[1];  
  47.         for(String deleteDataID : deleteFileIDs){  
  48.             //获取已删除元素对应的TermDocs  
  49.             TermDocs tds = reader.termDocs(new Term("fileID", deleteDataID));  
  50.             //将已删除元素的文档编号放到docs中,将其出现的频率放到freqs中,最后返回查询出来的元素数目  
  51.             int count = tds.read(docs, new int[1]);  
  52.             if(count == 1){  
  53.                 //将这个位置docs[0]的元素删除  
  54.                 obs.clear(docs[0]);  
  55.             }  
  56.         }  
  57.         return obs;  
  58.     }  
  59. }  
内容概要:本文介绍了多种开发者工具及其对开发效率的提升作用。首先,介绍了两款集成开发环境(IDE):IntelliJ IDEA 以其智能代码补全、强大的调试工具项目管理功能适用于Java开发者;VS Code 则凭借轻量级多种编程语言的插件支持成为前端开发者的常用工具。其次,提到了基于 GPT-4 的智能代码生成工具 Cursor,它通过对话式编程显著提高了开发效率。接着,阐述了版本控制系统 Git 的重要性,包括记录代码修改、分支管理协作功能。然后,介绍了 Postman 作为 API 全生命周期管理工具,可创建、测试文档化 API,缩短前后端联调时间。再者,提到 SonarQube 这款代码质量管理工具,能自动扫描代码并检测潜在的质量问题。还介绍了 Docker 容器化工具,通过定义应用的运行环境依赖,确保环境一致性。最后,提及了线上诊断工具 Arthas 性能调优工具 JProfiler,分别用于生产环境排障性能优化。 适合人群:所有希望提高开发效率的程序员,尤其是有一定开发经验的软件工程师技术团队。 使用场景及目标:①选择合适的 IDE 提升编码速度代码质量;②利用 AI 编程助手加快开发进程;③通过 Git 实现高效的版本控制团队协作;④使用 Postman 管理 API 的全生命周期;⑤借助 SonarQube 提高代码质量;⑥采用 Docker 实现环境一致性;⑦运用 Arthas JProfiler 进行线上诊断性能调优。 阅读建议:根据个人或团队的需求选择适合的工具,深入理解每种工具的功能特点,并在实际开发中不断实践优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值