Lucene实现简单的全文检索

Lucene索引与搜索实战
本文介绍如何使用Lucene建立文本索引及搜索功能,包括创建索引、实现文件检索及遍历文件系统索引.txt文件的过程。通过具体代码示例展示了如何利用Lucene进行高效的文本信息管理和检索。

一、索引小程序

1. 将所需要的lucene包导入到项目里。

2. 首先在LuceneIndex里new一个class,名字叫做Indexer。

3. 然后,在LuceneIndex工程里新建一个文件夹,叫做raw。

4. 接下来,在raw文件夹里新建两个utf-8编码的txt文件。比如第一个文件命名为hello.txt,内容为"Hello",第二个文件命名为nihao.txt,内容为"你好"。这里要注意的是,上面的代码是针对中文搜索的问题使用了utf-8编码,所以要求文件也是utf-8的编码。

5. 写入如下代码:

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.*;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;


/**
 * @author csl
 * @description: 
 * 依赖jar:Lucene-core,lucene-analyzers-common,lucene-queryparser
 * 作用:简单的索引建立
 */
public class Indexer {
    public static Version luceneVersion = Version.LATEST;
    
    /**
     * 建立索引
     */
    public static void createIndex(){
        IndexWriter writer = null;
        try{
            //1、创建Directory
            //Directory directory = new RAMDirectory();//创建内存directory
            Directory directory = FSDirectory.open(Paths.get("index"));//在硬盘上生成Directory00
            //2、创建IndexWriter
            IndexWriterConfig iwConfig = new IndexWriterConfig( new StandardAnalyzer());
            writer = new IndexWriter(directory, iwConfig);
            //3、创建document对象
            Document document = null;
            //4、为document添加field对象
            File f = new File("raw");//索引源文件位置
            for (File file:f.listFiles()){
                    document = new Document();
                    document.add(new StringField("path", f.getName(),Field.Store.YES));
                    System.out.println(file.getName());
                    document.add(new StringField("name", file.getName(),Field.Store.YES));
                    InputStream stream = Files.newInputStream(Paths.get(file.toString()));
                    document.add(new TextField("content", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));//textField内容会进行分词
                    //document.add(new TextField("content", new FileReader(file))); // 如果不用utf-8编码的话直接用这个就可以了
                    writer.addDocument(document);
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            //6、使用完成后需要将writer进行关闭
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) throws IOException
    {
        createIndex();
    }
}
6. 最后,运行Indexer.java。会看到索引建立完成。LuceneIndex工程下多了一个index文件夹。
二、检索小程序

下面我们就要用这个index来检索了。

new一个class,命名为Searcher。然后在里面写入如下代码:

import java.nio.file.Paths;
import java.io.*;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
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.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

/**
 * @author csl
 * @description: 
 * 依赖jar:Lucene-core,lucene-analyzers-common,lucene-queryparser
 * 作用:使用索引搜索文件
 */
public class Searcher {
    public static Version luceneVersion = Version.LATEST;
    /**
     * 查询内容
     */
    public static String indexSearch(String keywords){
        String res = "";
        DirectoryReader reader = null;
        try{
//            1、创建Directory
             Directory directory = FSDirectory.open(Paths.get("index"));//在硬盘上生成Directory
//            2、创建IndexReader
             reader = DirectoryReader.open(directory);
//            3、根据IndexWriter创建IndexSearcher
             IndexSearcher searcher =  new IndexSearcher(reader);
//            4、创建搜索的query
//            创建parse用来确定搜索的内容,第二个参数表示搜索的域
             QueryParser parser = new QueryParser("content",new StandardAnalyzer());//content表示搜索的域或者说字段
             Query query = parser.parse(keywords);//被搜索的内容
//            5、根据Searcher返回TopDocs
             TopDocs tds = searcher.search(query, 20);//查询20条记录
//            6、根据TopDocs获取ScoreDoc
             ScoreDoc[] sds = tds.scoreDocs;
//            7、根据Searcher和ScoreDoc获取搜索到的document对象
             int cou=0;
             for(ScoreDoc sd:sds){
                 cou++;
                 Document d = searcher.doc(sd.doc);
//                    8、根据document对象获取查询的字段值
                 /**  查询结果中content为空,是因为索引中没有存储content的内容,需要根据索引path和name从原文件中获取content**/
                 res+=cou+". "+d.get("path")+" "+d.get("name")+" "+d.get("content")+"\n";
             }

            
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            //9、关闭reader
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return res;
    }
    public static void main(String[] args) throws IOException
    {
        System.out.println(indexSearch("hi")); //搜索的内容可以修改
    }
}
搜索内容为"Hello"时,搜索结果为内容包含"Hello"的hello.txt。

三、遍历文件系统

这是一个简单的Lucene演示程序,只能索引同一目录下的txt文件,下面我来介绍一种遍历文件系统并且索引.txt文件的方法。

这个方法很简单,就是一个递归实现的深度优先遍历。

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.*;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
public class Indexall {
    static int numIndexed=0;
    //索引
    private static void indexFile(IndexWriter writer,File f) throws IOException
    {
        if(f.isHidden()||!f.exists()||!f.canRead())
        {
            return;
        }
        System.out.println("Indexing"+f.getCanonicalPath());
        Document document = new Document();
        document.add(new StringField("path", f.getName(),Field.Store.YES));
        System.out.println(f.getName());
        document.add(new StringField("name", f.getName(),Field.Store.YES));
        InputStream stream = Files.newInputStream(Paths.get(f.toString()));
        document.add(new TextField("content", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))));//textField内容会进行分词
        //document.add(new TextField("content", new FileReader(file)));  如果不用utf-8编码的话直接用这个就可以了
        writer.addDocument(document);
    }
    //深度优先遍历文件系统并索引.txt文件
    private static int indexDirectory(IndexWriter writer,File dir) throws IOException
    {
        
        File[] files=dir.listFiles();
        for(int i=0;i<files.length;i++)
        {
            File f=files[i];
            System.out.println(f.getAbsolutePath());
            if(f.isDirectory())
            {
                indexDirectory(writer,f);
            }
            else if(f.getName().endsWith(".txt"))
            {
                indexFile(writer,f);//递归
                numIndexed+=1;
            }
        }
        return numIndexed;
    }
    //创建IndexWriter并开始文件系统遍历
    public static int index(File indexDir,File dataDir) throws IOException
    {
        if(!dataDir.exists()||!dataDir.isDirectory())
        {
            throw new IOException(dataDir+"does not exist or is not a directory!");
        }
        Directory directory = FSDirectory.open(Paths.get("index"));
        IndexWriterConfig iwConfig = new IndexWriterConfig( new StandardAnalyzer());
        IndexWriter writer = new IndexWriter(directory, iwConfig);
        int numIndexed=indexDirectory(writer,dataDir);
        writer.close();
        return numIndexed;
    }
    public static void main(String[] args) throws Exception
    {
        File indexDir=new File("index");
        File dataDir=new File("raw");
        int numIndexed=index(indexDir,dataDir);
        System.out.println("Indexing " + numIndexed + " files");
    }
    

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值