在多个请求中使用indexSearcher的相同实例时出现问题

时间:2009-05-22 19:17:41

标签: lucene lucene.net

在.net网络应用程序中使用Lucene API。 我想为所有请求使用相同的Indexsearcher实例.Hence我将indexsearcher实例存储在http缓存中。

这是我的相同代码:

if (HttpRuntime.Cache["IndexSearcher"] == null)
                {
                    searcher = new IndexSearcher(jobIndexFolderPath);
                    HttpRuntime.Cache["IndexSearcher"] = searcher;
                }
                else
                {
                    searcher = (IndexSearcher)HttpRuntime.Cache["IndexSearcher"];
                }

当我执行下面的语句时,我收到一个运行时错误:“对象引用未设置为对象的实例。”

Hits hits = searcher.Search(myQuery);

我在这里缺少什么?

感谢阅读!

7 个答案:

答案 0 :(得分:4)

尝试以下内容:

protected static IndexSearcher searcher = null;
...

if (searcher == null)
{
    searcher = new IndexSearcher(jobIndexFolderPath);
}

答案 1 :(得分:1)

我还有一个使用Lucene API进行查询的Web应用程序(我的Web应用程序没有在索引上写入),我为每个请求创建了一个新的搜索器实例。它可能不是很“performant”,但我从未遇到过这种问题。

如果您愿意,我的网络应用程序位于Google Code上,您可以下载源代码并查看我的操作。这是项目http://code.google.com/p/goomez/

的网址

答案 2 :(得分:1)

首先,它根本不安全,应该是:

var searcher = (IndexSearcher)HttpRuntime.Cache["IndexSearcher"];
if(searcher == null)
{
     searcher = new IndexSearcher(jobIndexFolderPath);
     HttpRuntime.Cache["IndexSearcher"] = searcher;
}

在您的代码中,缓存可以在检查和分配之间过期

答案 3 :(得分:0)

两件事:

  1. 如果您使用的是.Net 2.0但尚未应用SP1,则this可能有所帮助。
  2. 查看人员遇到的问题this
  3. 这两个条目都指的是缓存中的对象过早过期 - 在两种情况下几乎都是立即过期的。由于缓存中的对象不是线程安全的,因此事情也可能变得复杂。

    如果您必须拥有一个IndexSearcher,为什么不将其作为服务提供给Web应用程序?

答案 4 :(得分:0)

我的快速回答是......

您并不需要为所有请求使用相同的索引搜索器对象,实际上我会建议不要使用它。您只需要确保只有一个线程更新索引。

如果你真的想要一个,那么应用程序中的静态成员变量如何被初始化一次并被所有人使用?

答案很长...... 我会尝试找到我的代码,看看我是如何处理问题的

答案 5 :(得分:0)

史蒂夫,见best ways of using IndexSearcher。这有点过时,但原则仍然是:使用IndexSearcher的单个实例,使用正确的线程安全代码(我不知道如何在.Net中)保护它,并在索引更新后使其无效。 我相信这就是杰西所建议的,我是第二个想法。

答案 6 :(得分:0)

而不是缓存indexSearcher,我现在正在缓存IndexReader。 如果IndexReader已经在缓存中,我会检查它是否是最新的。否则我打开它并将该实例传递给indexSearcher构造函数。

这个逻辑/代码是否有意义,优化搜索查询响应,因为多个请求正在点击Web服务器进行搜索?

感谢阅读。

string key = MyConstants.CacheKey.IndexReader;

            indexReader = MyCacheManager.Get<IndexReader>(key);

            if (indexReader == null)//cache is empty.open indexreader
            {
                indexReader = IndexReader.Open(myIndexFolderPath);
                MyCacheManager.Add(key, indexReader);
                indexSearcher = new IndexSearcher(indexReader);
            }
            else//cache contains indexreader...check if it is up to date
            {
                indexSearcher = base.GetIndexSearcher(myIndexFolderPath, indexReader);
            }
            protected IndexSearcher GetIndexSearcher(string indexFolderPath, IndexReader indexReader)
        {
            IndexSearcher indexSearcher = null;
            if (!indexReader.IsCurrent())//index is not up to date
            {
                indexReader = IndexReader.Open(indexFolderPath);

                indexSearcher = new IndexSearcher(indexReader);
            }
            else
            {
                indexSearcher = new IndexSearcher(indexReader);
            }

            return indexSearcher;

        }