• Lucene之删除索引


     

     

    分类: 【java】

    1.前言

    之前的博客《Lucene全文检索之HelloWorld》已经简单介绍了Lucene的索引生成和检索。本文着重介绍Lucene的索引删除。

    2.应用场景

    索引建立完成后,因为有些原因,被索引的文件已经删除。此时,索引仍然存在,为了不产生“虚假检索结果”,需要将失效的索引删除

    3.HelloLucene类(重点关注deleteIndexByQuery方法)

    [java] view plaincopy
     
    1. package com.njupt.zhb;  
    2.   
    3. import java.io.BufferedReader;  
    4. import java.io.File;  
    5. import java.io.FileInputStream;  
    6. import java.io.FileNotFoundException;  
    7. import java.io.IOException;  
    8. import java.io.InputStreamReader;  
    9. import org.apache.lucene.analysis.Analyzer;  
    10. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
    11. import org.apache.lucene.document.Document;  
    12. import org.apache.lucene.document.Field;  
    13. import org.apache.lucene.document.LongField;  
    14. import org.apache.lucene.document.StringField;  
    15. import org.apache.lucene.document.TextField;  
    16. import org.apache.lucene.index.DirectoryReader;  
    17. import org.apache.lucene.index.IndexReader;  
    18. import org.apache.lucene.index.IndexWriter;  
    19. import org.apache.lucene.index.IndexWriterConfig;  
    20. import org.apache.lucene.index.IndexWriterConfig.OpenMode;  
    21. import org.apache.lucene.index.Term;  
    22. import org.apache.lucene.queryparser.classic.ParseException;  
    23. import org.apache.lucene.queryparser.classic.QueryParser;  
    24. import org.apache.lucene.search.IndexSearcher;  
    25. import org.apache.lucene.search.Query;  
    26. import org.apache.lucene.search.ScoreDoc;  
    27. import org.apache.lucene.search.TopDocs;  
    28. import org.apache.lucene.store.Directory;  
    29. import org.apache.lucene.store.FSDirectory;  
    30. import org.apache.lucene.util.Version;  
    31. /* 
    32.  *@author: ZhengHaibo   
    33.  *web:     http://blog.csdn.net/nuptboyzhb 
    34.  *mail:    zhb931706659@126.com 
    35.  *2013-08-27  Nanjing,njupt,China 
    36.  */  
    37. public class HelloLucene {  
    38.     /** 
    39.      * Index all text files under a directory. 
    40.      * String indexPath = "index";//索引保存的路径 
    41.      * String docsPath = "";//文档保存的路径(待索引) 
    42.      */  
    43.     public void index(String indexPath,String docsPath) {  
    44.         try {  
    45.             // 1.创建Directory  
    46.             Directory dir = FSDirectory.open(new File(indexPath));//保存在硬盘上  
    47.             // 2.创建IndexWriter  
    48.             Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_44);  
    49.             IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_44,  
    50.                     analyzer);  
    51.             iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);// 设置创建或追加模式  
    52.             IndexWriter writer = new IndexWriter(dir, iwc);  
    53.             final File docDir = new File(docsPath);  
    54.             indexDocs(writer, docDir);  
    55.             writer.close();  
    56.         } catch (IOException e) {  
    57.             // TODO Auto-generated catch block  
    58.             e.printStackTrace();  
    59.         }  
    60.     }  
    61.       
    62.     public void indexDocs(IndexWriter writer, File file) throws IOException {  
    63.         if (file.canRead()) {  
    64.             if (file.isDirectory()) {//如果是文件夹,则遍历文件夹内的所有文件  
    65.                 String[] files = file.list();  
    66.                 // an IO error could occur  
    67.                 if (files != null) {  
    68.                     for (int i = 0; i < files.length; i++) {  
    69.                         indexDocs(writer, new File(file, files[i]));  
    70.                     }  
    71.                 }  
    72.             } else {//如果是文件  
    73.                 FileInputStream fis;  
    74.                 try {  
    75.                     fis = new FileInputStream(file);  
    76.                 } catch (FileNotFoundException fnfe) {  
    77.                     return;  
    78.                 }  
    79.                 try {  
    80.                     // 3.创建Document对象  
    81.                     Document doc = new Document();  
    82.                     // 4.为Document添加Field  
    83.                     // Add the path of the file as a field named "path". Use a  
    84.                     // field that is indexed (i.e. searchable), but don't  
    85.                     // tokenize  
    86.                     // the field into separate words and don't index term  
    87.                     // frequency  
    88.                     // or positional information:  
    89.                     //以文件的文件路径建立Field  
    90.                     Field pathField = new StringField("path", file.getPath(),Field.Store.YES);  
    91.                     doc.add(pathField);//添加到文档中  
    92.                     //以文件的名称建立索引域  
    93.                     doc.add( new StringField("filename", file.getName(),Field.Store.YES));//添加到文档中  
    94.                     // Add the last modified date of the file a field named  
    95.                     // "modified".  
    96.                     // Use a LongField that is indexed (i.e. efficiently  
    97.                     // filterable with  
    98.                     // NumericRangeFilter). This indexes to milli-second  
    99.                     // resolution, which  
    100.                     // is often too fine. You could instead create a number  
    101.                     // based on  
    102.                     // year/month/day/hour/minutes/seconds, down the resolution  
    103.                     // you require.  
    104.                     // For example the long value 2011021714 would mean  
    105.                     // February 17, 2011, 2-3 PM.  
    106.                     doc.add(new LongField("modified", file.lastModified(),Field.Store.YES));  
    107.                     // Add the contents of the file to a field named "contents".  
    108.                     // Specify a Reader,  
    109.                     // so that the text of the file is tokenized and indexed,  
    110.                     // but not stored.  
    111.                     // Note that FileReader expects the file to be in UTF-8  
    112.                     // encoding.  
    113.                     // If that's not the case searching for special characters  
    114.                     // will fail.  
    115.                     //以文件的内容建立索引域(Field)  
    116.                     doc.add(new TextField("contents", new BufferedReader(new InputStreamReader(fis, "UTF-8"))));  
    117.                     if (writer.getConfig().getOpenMode() == OpenMode.CREATE) {  
    118.                         // New index, so we just add the document (no old  
    119.                         // document can be there):  
    120.                         System.out.println("adding " + file);  
    121.                         writer.addDocument(doc);//将文档写入到索引中(以创建的方式)  
    122.                     } else {  
    123.                         // Existing index (an old copy of this document may have  
    124.                         // been indexed) so  
    125.                         // we use updateDocument instead to replace the old one  
    126.                         // matching the exact  
    127.                         // path, if present:  
    128.                         System.out.println("updating " + file);       
    129.                         writer.updateDocument(new Term("path", file.getPath()),doc);//以追加方式写入到索引中  
    130.                     }  
    131.                 } finally {  
    132.                     fis.close();  
    133.                 }  
    134.             }  
    135.         }  
    136.     }  
    137.     /** 
    138.      * 搜索 
    139.      * http://blog.csdn.net/nuptboyzhb 
    140.      */  
    141.     public void searcher(String indexPath,String searchKeyword){  
    142.         try {  
    143.             IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(indexPath)));  
    144.             IndexSearcher searcher = new IndexSearcher(reader);  
    145.             Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_44);  
    146.             String field = "contents";//搜索域是:文档的内容  
    147.             QueryParser parser = new QueryParser(Version.LUCENE_44, field, analyzer);  
    148.             Query query= parser.parse(searchKeyword);//搜索内容中含有searchKeyword字符串的文档  
    149.             TopDocs tds=searcher.search(query, 10);//搜索前十个  
    150.             ScoreDoc[] sds= tds.scoreDocs;  
    151.             for (ScoreDoc sd:sds) {//将内容中含有“南京”关键字的文档遍历一遍  
    152.                 Document document=searcher.doc(sd.doc);  
    153.                 System.out.println("score:"+sd.score+"--filename:"+document.get("filename")+  
    154.                         "--path:"+document.get("path")+"--time"+document.get("modified"));//打印检索结果中文档的路径  
    155.             }  
    156.             reader.close();  
    157.         } catch (IOException e) {  
    158.             // TODO Auto-generated catch block  
    159.             e.printStackTrace();  
    160.         }catch (ParseException e) {  
    161.             // TODO Auto-generated catch block  
    162.             e.printStackTrace();  
    163.         }  
    164.     }  
    165.     /** 
    166.      * 删除索引 
    167.      * @param indexPath 索引所在的路径 
    168.      * @param deleteKeyword 删除含有该内容的索引 
    169.      */  
    170.     public void deleteIndexByQuery(String indexPath,String deleteKeyword){  
    171.         try {  
    172.             //1.新建一个IndexWrite  
    173.             IndexWriter writer = new IndexWriter(FSDirectory.open(new File(indexPath)),new IndexWriterConfig(Version.LUCENE_44, new StandardAnalyzer(Version.LUCENE_44)));  
    174.             //2.生成一个Query  
    175.             Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_44);  
    176.             String field = "contents";//搜索域是:文档的内容  
    177.             QueryParser parser = new QueryParser(Version.LUCENE_44, field, analyzer);  
    178.             Query query= parser.parse(deleteKeyword);//生成搜索内容中含有deleteKeyword的文档  
    179.             //3.按Query参数的方式删除索引,即删除了含有deleteKeyword的索引  
    180.             writer.deleteDocuments(query);  
    181.             writer.commit();//提交,正是删除  
    182.             writer.close();//关闭  
    183.             //  
    184.             //writer.deleteDocuments(new Term(field, ""));  
    185.         }catch (IOException e) {  
    186.             // TODO Auto-generated catch block  
    187.             e.printStackTrace();  
    188.         }catch (ParseException e) {  
    189.             // TODO Auto-generated catch block  
    190.             e.printStackTrace();  
    191.         }  
    192.     }  
    193. }  


    4.编写Junit测试

    [java] view plaincopy
     
    1. package com.njupt.zhb;  
    2.   
    3. import org.junit.Test;  
    4. /* 
    5.  *@author: ZhengHaibo   
    6.  *web:     http://blog.csdn.net/nuptboyzhb 
    7.  *mail:    zhb931706659@126.com 
    8.  *2013-08-25  Nanjing,njupt,China 
    9.  */  
    10. public class TestJunit {  
    11.    @Test  
    12.    public void TestIndex(){  
    13.        HelloLucene hLucene=new HelloLucene();  
    14.        hLucene.index("index", "D:\lucene");  
    15.    }  
    16.    @Test  
    17.    public void TestSearcher(){  
    18.        HelloLucene hLucene=new HelloLucene();  
    19.        hLucene.searcher("index","南京");  
    20.    }  
    21.    @Test  
    22.    public void TestDeleteIndexByQuery(){  
    23.        HelloLucene hLucene=new HelloLucene();  
    24.        System.out.println("未删除前,查询关键字:北京  --结果:");  
    25.        hLucene.searcher("index","北京");  
    26.        hLucene.deleteIndexByQuery("index", "北京");  
    27.        System.out.println("删除后,查询关键字:北京  --结果:");  
    28.        hLucene.searcher("index","北京");  
    29.    }  
    30. }  


    5.实验结果

    5.1运行TestIndex方法

    >控制台打印的信息

    [html] view plaincopy
     
    1. updating D:lucenelucene1.txt  
    2. updating D:lucenelucene2.txt  
    3. updating D:lucenelucene3.txt  
    4. updating D:lucene北京.txt  
    5. updating D:lucene南京.txt  

    此时的index目录下的截图:

    5.2运行TestSearcher方法

    >搜索含有关键字“南京”的文档

    [html] view plaincopy
     
    1. score:0.53033006--filename:lucene3.txt--path:D:lucenelucene3.txt--time1376828819375  
    2. score:0.48666292--filename:lucene2.txt--path:D:lucenelucene2.txt--time1376828783791  
    3. score:0.2155931--filename:北京.txt--path:D:lucene北京.txt--time1377784223795  
    4. score:0.1530931--filename:南京.txt--path:D:lucene南京.txt--time1377784261486  


    5.3运行TestDeleteIndexByQuery方法

    >

    [html] view plaincopy
     
    1. 未删除前,查询关键字:北京  --结果:  
    2. score:0.4847152--filename:lucene2.txt--path:D:lucenelucene2.txt--time1376828783791  
    3. score:0.39226472--filename:北京.txt--path:D:lucene北京.txt--time1377784223795  
    4. score:0.10348864--filename:lucene3.txt--path:D:lucenelucene3.txt--time1376828819375  
    5. score:0.029874597--filename:南京.txt--path:D:lucene南京.txt--time1377784261486  
    6. 删除后,查询关键字:北京  --结果:  
    删除后,再次查询关键字时,无查询结果。

    此时,index目录下的文件结构为:

    多出了一个_0_1.del文件

    项目源代码:http://download.csdn.net/detail/nuptboyzhb/6041239

    未经允许,不得用于商业目的

  • 相关阅读:
    C++输入cout与输出cin
    golang学习笔记
    vscode环境配置
    golang 微框架 gin
    git go使用socket5代理
    go包管理工具glide
    collectd的python插件(redis)
    zookeeper & kafka 集群
    redis复制集(sentinel)
    python加解密
  • 原文地址:https://www.cnblogs.com/u0mo5/p/4168483.html
Copyright © 2020-2023  润新知