lucene3.5通过NRTManager和SearchManager实现近实时搜索

本文详细介绍了Lucene中实现近实时搜索的方法,包括如何通过NRTManager类来实现实时和近实时的索引更新及查询。重点讨论了如何在索引发生改变时,通过线程跟踪来快速响应用户程序的调用,以及如何通过内存操作避免频繁的磁盘I/O操作。此外,文章还提供了关键代码示例,展示了如何在不改变硬盘索引库的情况下更新和删除文档。

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

实时搜索(近实时搜索)
     完全的实时搜索:只要数据库一变动,马上要更新索引,writer.commit来操作

    近实时搜索:当用户修改了信息之后,先把索引保存到内存中,然后在一个统一的时间对内存中的所有的索引进行提交操作。

reopen,NRTManager(near-real-time)


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对象来获取最

新索引。

以下是相关代码:

 private SearcherManager mgr = null;
            private NRTManager nrtMgr = null;
            private IndexWriter writer = null;

            writer = new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35)));
            nrtMgr = new NRTManager (writer,new SearcherWarmer() {
                @Override
                public void warm(IndexSearcher s) throws IOException {
                    System.out.println("reopen");
                }
            });
            //启动NRTManager的Reopen线程
            NRTManagerReopenThread reopen = new NRTManagerReopenThread(nrtMgr, 5.0,0.025);
            reopen.setDaemon(true);
            reopen.setName("NrtManager Reopen Thread");
            reopen.start();
            mgr = nrtMgr.getSearcherManager(true);

    public void delete() {
        try {
            nrtMgr.deleteDocuments (new Term("id","2"));
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (LockObtainFailedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void update() {
        try {
            /*
             * Lucene并没有提供更新,这里的更新操作其实是如下两个操作的合集
             * 先删除之后再添加
             */
            Document doc = new Document();
            doc.add(new Field("id","11",Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
            doc.add(new Field("email",emails[0],Field.Store.YES,Field.Index.NOT_ANALYZED));
            doc.add(new Field("content",contents[0],Field.Store.NO,Field.Index.ANALYZED));
            doc.add(new Field("name",names[0],Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
            nrtMgr.updateDocument (new Term("id","1"), doc);
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (LockObtainFailedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void search02() {
        IndexSearcher searcher = mgr.acquire(); 
        try {
//            mgr.maybeReopen();//判断是否需要重新打开一个searcher
            TermQuery query = new TermQuery(new Term("content","like"));
            TopDocs tds = searcher.search(query, 10);
            for(ScoreDoc sd:tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println(doc.get("id")+"---->"+
                        doc.get("name")+"["+doc.get("email")+"]-->"+doc.get("id")+","+
                        doc.get("attach")+","+doc.get("date"));
            }
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                mgr.release(searcher); 
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值