初识Lucene(下)

版权声明:欢迎转载,若有不当之处请在评论中指出,共同交流。 https://blog.csdn.net/qq_33290787/article/details/52190500

本文将给出Lucene 6.1.0的代码实现与讲解。请确保已经阅读:初始Lucene(上)。Lucene从最初的1.9.1更新到现在的6.1.0。在这个过程中一些接口已经被弃用,也有新功能的加入,因此不同版本的Lucene代码实现方式可能是不一样的,具体版本的代码实现可以查看官方文档Lucene 6.1.0 API,这是6.1.0版本的使用文档。


项目开始之前,要进行Lucene 6.1.0相关jar包的导入,jar包下载地址http://lucene.apache.org/core/index.html

这里写图片描述

步骤一:创建一个IndexWriter对象为待搜索的文档创建索引文件:

// 创建Directory
Directory directory = FSDirectory.open( FileSystems.getDefault().getPath("C:/Users/Administrator/Desktop/LuceneIndex"));
// 创建IndexWriter
Analyzer analyzer = new StandardAnalyzer();
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
indexWriter = new IndexWriter(directory, indexWriterConfig);
indexWriter.deleteAll();//清空以前的index

步骤二:打开硬盘中的文件,读取文件中的内容,创建索引文件:

//要搜索的File路径,路径下全是后缀名为.txt的文档
File dFile = new File("C:/Users/Administrator/Desktop/File");
File[] files = dFile.listFiles();
for (File file : files) {
    // 创建Document对象
    Document document = new Document();
    // 为Document添加Field           
    document.add(new Field("content",content,TextField.TYPE_STORED));
    document.add(new Field("filename", file.getName(), TextField.TYPE_STORED));
    document.add(new Field("filepath", file.getAbsolutePath(), TextField.TYPE_STORED));
    // 通过IndexWriter添加文档到索引中
    indexWriter.addDocument(document);

    /*其实Document对象相当于数据库中的表,为它添加的Field(域)相当于数据表中的字段。在写入索引
     * 文件indexWriter.addDocument(document)操作时,相当于为单词词库中的关键词建立相
     * 应倒排文件的指针,产生一种映射关系。在这里"content"域静态变量可以设置为TYPE_NOT_STORED,
     * 因为倒排文件已经保存了"filepath",搜索过后可以通过路径再到硬盘中得到文本内容。*/

}

经过步骤一与步骤二,已经完成为待搜索文件创建索引的工作,下面就开始搜索。

步骤三:搜索文本时,创建IndexSearch索引搜索对象:

// 创建Directory  
Directory directory = FSDirectory.open( FileSystems.getDefault().getPath("C:/Users/Administrator/Desktop/LuceneIndex"));
// 创建IndexReader  
directoryReader = DirectoryReader.open(directory);  
// 根据IndexReader创建IndexSearch  
IndexSearcher indexSearcher = new IndexSearcher(directoryReader);

步骤四:创建Query对象:

// 创建搜索的Query  
Analyzer analyzer = new StandardAnalyzer();  
// 创建parser来确定要搜索文件的内容,第一个参数为搜索的域  
QueryParser queryParser = new QueryParser("content", analyzer);  
// 创建Query表示搜索域为content包含keyWord的文档  
Query query = queryParser.parse(keyWord); 

步骤五:得到搜索结果与代码高亮:

// 根据searcher搜索并且返回TopDocs  
TopDocs topDocs = indexSearcher.search(query, 1000);  
System.out.println("查找到的文档总共有:"+topDocs.totalHits);

// 根据TopDocs获取ScoreDoc对象  
ScoreDoc[] scoreDocs = topDocs.scoreDocs;  
for (ScoreDoc scoreDoc : scoreDocs) {  
    // 根据searcher和ScoreDoc对象获取具体的Document对象  
    Document document = indexSearcher.doc(scoreDoc.doc);  
    // 根据Document对象获取需要的值  
    System.out.println(document.get("filename") + " " + document.get("filepath")); 
    System.out.println(document.get("content"));//得到搜索结果
    String value = toHighlighter(query,document,"content",analyzer);
    System.out.println(value);//得到搜索结果,带有关键词高亮
}

完整代码:

package HighLightSearch;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.FileSystems;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

class Index {
    // 建立索引
    public void index() {
        IndexWriter indexWriter = null;
        try {
            // 创建Directory
            Directory directory = FSDirectory.open(
                    FileSystems.getDefault().getPath("C:/Users/Administrator/Desktop/LuceneIndex"));
            // 创建IndexWriter
            Analyzer analyzer = new StandardAnalyzer();
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
            indexWriter = new IndexWriter(directory, indexWriterConfig);
            indexWriter.deleteAll();//清除以前的index

            //要搜索的File路径,路径下全是后缀名为.txt的文档
            File dFile = new File("C:/Users/Administrator/Desktop/File");
            File[] files = dFile.listFiles();
            for (File file : files) {
                //读取文档中的内容至content字符串中
                 BufferedReader in = new BufferedReader(new FileReader(file)); 
                 String s;
                 String content = "";
                 while((s = in.readLine()) != null){//readLine()方法每次读取文件的一行直到遇到换行符
                     content += s+"\n";
                 }
                 in.close();

                 File outputFile = new File("C:/Users/Administrator/Desktop/LuceneOutput/"+file.getName());
                 if(!outputFile.exists()){
                     System.out.print("创建文件:"+file.getName());
                     outputFile.createNewFile();
                 }

                 //将字符串的内容写入输出文档中
                 BufferedWriter bw = new BufferedWriter(
                         new OutputStreamWriter(
                                 new FileOutputStream("C:/Users/Administrator/Desktop/LuceneOutput/"+file.getName())));
                 bw.write(content);
                 bw.close();

                // 创建Document对象
                Document document = new Document();
                // 为Document添加Field           
                document.add(new Field("content",content, TextField.TYPE_STORED));
                document.add(new Field("filename", file.getName(), TextField.TYPE_STORED));
                document.add(new Field("filepath", file.getAbsolutePath(), TextField.TYPE_STORED));

                // 通过IndexWriter添加文档到索引中
                indexWriter.addDocument(document);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (indexWriter != null) {
                    indexWriter.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}


class Search {  
    public void search(String keyWord) {  
        DirectoryReader directoryReader = null;  
        try {  
            // 创建Directory  
            Directory directory = FSDirectory.open(
                    FileSystems.getDefault().getPath("C:/Users/Administrator/Desktop/LuceneIndex"));
            // 创建IndexReader  
            directoryReader = DirectoryReader.open(directory);  
            // 根据IndexReader创建IndexSearch  
            IndexSearcher indexSearcher = new IndexSearcher(directoryReader);  

            // 创建搜索的Query  
            Analyzer analyzer = new StandardAnalyzer();  
            // 创建parser来确定要搜索文件的内容,第一个参数为搜索的域  
            QueryParser queryParser = new QueryParser("content", analyzer);  
            // 创建Query表示搜索域为content包含UIMA的文档  
            Query query = queryParser.parse(keyWord);  

            // 根据searcher搜索并且返回TopDocs  
            TopDocs topDocs = indexSearcher.search(query, 1000);  
            System.out.println("查找到的文档总共有:"+topDocs.totalHits);

            // 根据TopDocs获取ScoreDoc对象  
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;  
            for (ScoreDoc scoreDoc : scoreDocs) {  

                // 根据searcher和ScoreDoc对象获取具体的Document对象  
                Document document = indexSearcher.doc(scoreDoc.doc);  

                // 根据Document对象获取需要的值  
                System.out.println(document.get("filename") + " " + document.get("filepath")); 
                System.out.println(document.get("content"));//得到搜索结果

                String value = toHighlighter(query,document,"content",analyzer);
                System.out.println(value);//得到搜索结果,带有关键词高亮
            }  

        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if (directoryReader != null) {  
                    directoryReader.close();  
                }  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
    }

    //高亮
    public String toHighlighter(Query query,Document doc,String field,Analyzer analyzer){
        try {
            SimpleHTMLFormatter simpleHtmlFormatter = new SimpleHTMLFormatter("<font color=\"red\">", "</font>");
            Highlighter highlighter = new Highlighter(simpleHtmlFormatter,new QueryScorer(query));
            TokenStream tokenStream1 = analyzer.tokenStream("text",new StringReader(doc.get(field)));
            String highlighterStr = highlighter.getBestFragment(tokenStream1, doc.get(field));
            return highlighterStr == null ? doc.get(field):highlighterStr;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidTokenOffsetsException e) {
            e.printStackTrace();
            return null;
        }
    }
}  

public class HighLightSearch {
    //测试
    public static void main(String[] args) {
        Index newIndex = new Index();
        newIndex.index();
        Search newSearch = new Search();
        newSearch.search("今天总结Lucene");
    }
}

运行结果:

查找到的文档总共有:2
hhh.txt C:\Users\Administrator\Desktop\File\hhh.txt
今天是2016812号。开始总结Lucene了,并且打算运用Lucene至项目中

<font color="red">今</font><font color="red">天</font>是2016812号。开始<font color="red">总</font><font color="red">结</font><font color="red">Lucene</font>了,并且打算运用<font color="red">Lucene</font>至项目中

goal.txt C:\Users\Administrator\Desktop\File\goal.txt
数据库
Spring+SpringMVC+MyBatis+Maven(项目)
常用算法(数据结构)
CSS3
(JS,node.js)

数据库
Spring+SpringMVC+MyBatis+Maven(项目)
常用算法(数据<font color="red">结</font>构)
CSS3
(JS,node.js)

项目源码地址,欢迎Fork与Star~:

https://github.com/HuangFuGui/Javaweb/tree/master/LuceneProject


猜你喜欢

转载自blog.csdn.net/qq_33290787/article/details/52190500
今日推荐