IndexWriter和IndexSearcher Lucene.net的单例模式

时间:2013-01-23 06:04:02

标签: lucene.net

我正在使用 Lucene.net 3.0.3.0 (目前是最新版本)。我想知道在生产环境中使用 IndexWriter IndexSearcher 的单个实例是否是一个不错的选择(考虑线程安全性)。我在文档中读到,创建这些实例的新对象是一项昂贵的操作,并且内部lucene很好地处理并发请求。

对于在生产环境中使用lucene.net的人来说,这是一个问题;请告诉我这是否有效!

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Lucene.Net.Search;
    using Lucene.Net.Store;
    using System.IO;

    using Directory = Lucene.Net.Store.Directory;
    using Version = Lucene.Net.Util.Version;
    using Lucene.Net.Index;
    using Lucene.Net.Analysis.Standard;
    using Lucene.Net.Analysis;

    namespace MXLuceneConsoleApp
    {
        /// <summary>
        /// This helper class applies a singleton pattern to create Searcher and Writer objects as it's recommended to create them only once.
        /// Also the searcher gets reinitialized, if any write happens.    
        /// </summary>
        public class MXLuceneIndexHelper
        {
            private static IndexSearcher _searcher;        
            private static Directory _directory;
            private static Lazy<IndexWriter> _writer = new Lazy<IndexWriter>(() => new IndexWriter(_directory, new StandardAnalyzer(Version.LUCENE_30), IndexWriter.MaxFieldLength.UNLIMITED));

            //this private constructor makes it a singleton now.
            private MXLuceneIndexHelper() { }

            //Static constructor, opening the directory once for all.
            static MXLuceneIndexHelper()
            {
                _directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndexDir"));
            }

            public static IndexSearcher IndexSearcher
            {
                get
                {
                    if (_searcher == null)
                    {
                        InitializeSearcher();
                    }
                    else if (!_searcher.IndexReader.IsCurrent())
                    {                    
                        //_searcher.IndexReader.Reopen(); 
                        //refreshing the underlying Reader above doesn't do the trick, so I'm reinitializing the Searcher.
                        _searcher.Dispose();
                        InitializeSearcher();
                    }

                    return _searcher;
                }
            }

            public static IndexWriter IndexWriter
            {
                get 
                {                
                    //_writer.SetRAMBufferSizeMB(30.0);
                    return _writer.Value; 
                }
            }

            private static void InitializeSearcher()
            {
                _searcher = new IndexSearcher(_directory, false);

            }
        }//End of class
    }

1 个答案:

答案 0 :(得分:3)

我的理解是每个索引应该只有1个IndexWriter实例。默认情况下,Lucene中启用了内置锁定以确保此条件。至于单例模式,我认为你应该看看.NET 4中新的Lazy类。它免费处理所有锁定和空检查。

对于IndexSearcher,您可以随意拥有任意数量的实例。但是,如果您重用现有的搜索器,我认为可以获得性能提升。我可以从你的代码中看出,你知道重新打开一个现有的搜索者要比创建一个新搜索者便宜得多。此外,搜索器中还有内置缓存,当您进行第一次搜索时,它会被初始化。您还可以实现IndexReaderWarmer来控制搜索器何时变暖(如第一次搜索之前)。