Lucene.net 实现近实时搜索(NRT)和增量索引

Lucene做站内搜索的时候经常会遇到实时搜索的应用场景,比如用户搜索的功能。实现实时搜索,最普通的做法是,添加新的document之后,调用 IndexWriter 的 Commit 方法把内存中的索引提交到硬盘;然后重新打开IndexReader,进行搜索。但是索引一般存储在硬盘上,而且当索引文件比较大的时候,Commit操作和重新打开IndexReader效率比较低。

于是就想,可否一份索引的IndexWriter始终打开,当需要添加或删除Document时,直接调用该IndexWriter,从而实现增量索引;对于需要需要实现近实时搜索的索引,可以通过IndexReader的IsCurrent方法判断,如果有索引更新,则返回false,这时候需要调用IndexReader的Reopen()方法得到新的IndexReader对象,重新创建IndexSearcher对象即可。

至于IndexWriter何时Commit,可以使用定时任务,半分钟调用一次,也可以在意外情况下通过外部代码调用。

近实时搜索的实现

实现近实时搜索,需要保持IndexWriter打开,在索引有了增加或删除操作后,通过IndexReader的Reopen方法。

需要注意的问题有:线程同步、IndexReader的引用计数。

增量索引

/// <summary>
/// 添加索引内容
/// </summary>
/// <param name="indexDocuments">待添加的索引文档</param>
/// <param name="reopen">是否重新打开索引</param>
public void Insert(IEnumerable<Document> indexDocuments, bool reopen = true)
{
    lock (_lock)
    {
        if (indexDocuments == null || !indexDocuments.Any())
        {
            return;
        }
        IndexWriter indexWriter = GetIndexWriter();

        try
        {
            foreach (Document doc in indexDocuments)
            {
                indexWriter.AddDocument(doc);
            }
        }
        catch (Exception ex)
        {
            throw new ExceptionFacade(string.Format("An unexpected error occured while add documents to the index [{0}].", this.indexPath), ex);
        }

        if (reopen)
        {
            ReopenSearcher();
        }
    }
}
/// <summary>
/// 删除索引内容
/// </summary>
/// <param name="ids">索引内容对应的实体主键</param>
/// <param name="fieldNameOfId">实体主键对应的索引字段名称</param>
/// <param name="reopen">是否重新打开NRT查询</param>
public void Delete(IEnumerable<string> ids, string fieldNameOfId, bool reopen = true)
{
    lock (_lock)
    {
        if (ids == null && ids.Count() == 0)
        {
            return;
        }

        IndexWriter indexWriter = GetIndexWriter();
        try
        {
            List<Term> terms = new List<Term>();
            foreach (var id in ids)
            {
                Term term = new Term(fieldNameOfId, id);
                terms.Add(term);
            }

            indexWriter.DeleteDocuments(terms.ToArray());
        }
        catch (Exception ex)
        {
            throw new ExceptionFacade(string.Format("An unexpected error occured while delete documents to the index [{0}].", this.indexPath), ex);
        }

        if (reopen)
        {
            ReopenSearcher();
        }
    }
}

Lucene.net 实现近实时搜索(NRT)和增量索引

时间: 2024-08-26 14:35:56

Lucene.net 实现近实时搜索(NRT)和增量索引的相关文章

Lucene实现SearchManager近实时搜索

lucene通过NRTManager这个类来实现近实时搜索,所谓近实时搜索即在索引发生改变时,通 过线程跟踪,在相对很短的时间反映给给用户程序的调用 NRTManager通过管理IndexWriter对象,并将IndexWriter的一些方法(增删改)例如 addDocument,deleteDocument等方法暴露给客户调用,它的操作全部在内存里面,所以如果 你不调用IndexWriter的commit方法,通过以上的操作,用户硬盘里面的索引库是不会变化的,所 以你每次更新完索引库请记得co

solr 近实时搜索

摘要: Solr的近实时搜索NRT(Near Real Time Searching)意味着文档可以在索引以后马上可以被查询到. Solr不会因为本次提交而阻塞更新操作,不会等待后台合并操作(merge)的完成而是直接检索索引并返回数据.参见原文 利用NRT,就可以设置soft commit,因为标准的commit操作代价高昂,soft commit可以做到近乎实时的查询效果而不丢失数据. Commits 与 Optimizing 一个commit操作可以使新的查询请求能够感知到索引的变化,一般

剖析Elasticsearch集群系列之三:近实时搜索、深层分页问题和搜索相关性权衡之道

转载:http://www.infoq.com/cn/articles/anatomy-of-an-elasticsearch-cluster-part03 近实时搜索 虽然Elasticsearch中的变更不能立即可见,它还是提供了一个近实时的搜索引擎.如前一篇中所述,提交Lucene的变更到磁盘是一个代价昂贵的操作.为了避免在文档对查询依然有效的时候,提交变更到磁盘,Elasticsearch在内存缓冲和磁盘之间提供了一个文件系统缓存.内存缓存(默认情况下)每1秒刷新一次,在文件系统缓存中使

lucene4之后的近实时搜索实现

好久没干这块东西了,近几天需要做这个,所以重新学了一下,首先非常感谢孔浩老师,没孔浩老师的视频我也不会进入lucene的殿堂. 老师当时讲的实时搜索还是NRTManager,现在已经都变了,这个类已经不存在了,在4.0之后消失的,到我现在使用的5.2.1都是下面的方法: 首先罗列会使用的特殊类(常用的不再赘述): TrackingIndexWriter  追踪writer,在api中有介绍,只有通过这个类进行更新ControlledRealTimeReopenThread才能获得更新 Contr

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

实时搜索(近实时搜索) 完全的实时搜索:只要数据库一变动,马上要更新索引,writer.commit来操作 近实时搜索:当用户修改了信息之后,先把索引保存到内存中,然后在一个统一的时间对内存中的所有的索引进行提交操作. reopen,NRTManager(near-real-time) lucene通过NRTManager这个类来实现近实时搜索,所谓近实时搜索即在索引发生改变时,通过线程跟踪,在相对很短的时间反映给给用户程序的调用. NRTManager通过管理IndexWriter对象,并将I

基于Lucene的近实时搜索引擎优化总结

一.搜索优化: 在工程领域,越是看起来“简单.确定”的问题,越是难以解决.近实时搜索引擎需要解决的问题只有一个:性能!它包含快速索引,快速搜索,以及索引到搜索的快速生效. 以下为百万条数据级(适用于千万级)快速滚动数据近实时搜索引擎实践经验总结:  1. 针对技术优化 1.1 数值搜索优化: 将数值的范围缩小,能用 int值 的不要用 long值,能用 float值 的不用要 double值:能用string 替换的,就不要用范围查询(特别是大范围查询),这些都基于Lucene搜索引擎对数值建索

Solr -- 实时搜索

在solr中,实时搜索有3种方案 ①soft commit,这其实是近实时搜索,不能完全实时. ②RealTimeGet,这是实时,但只支持根据文档ID的查询. ③和第一种类似,只是触发softcommit. 综上,其实是由实时(②)和近实时(①③)两种. solr4.0 之后使用NRT的方法和需要的配置 方案1 使用soft commit达到近实时搜索的效果. 为了使用soft commit ,需要配置solrconfig.xml.其中两个地方需要修改 <autoCommit> <ma

一步一步跟我学习lucene(19)---lucene增量更新和NRT(near-real-time)Query近实时查询

这两天加班,不能兼顾博客的更新,请大家见谅. 有时候我们创建完索引之后,数据源可能有更新的内容,而我们又想像数据库那样能直接体现在查询中,这里就是我们所说的增量索引.对于这样的需求我们怎么来实现呢?lucene内部是没有提供这种增量索引的实现的: 这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建.对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况

初识Lucene 4.5.0 全文搜索--(二)

上一篇文章初识Lucene 4.5.0--(一)已经介绍了如何创建索引与检索索引.接下来就是删除与更新啦~ 一.删除索引. 原本3.x版本时 IndexWriter 与 IndexReader 都是有删除方法的,让我们先来看看lucene 3.6 api文档中的IndexReader的描述: 从4.0开始已经被删除了,所以现在只能用IndexWriter中的方法来进行删除.有哪些方法呢?继续看文档(lucene 4.5 api): 除了上面的六个外还有一个方法tryDeleteDocument(