2

我在 .net Web 应用程序中使用 Lucene API。我想对所有请求使用相同的 Indexsearcher 实例。因此我将 indexsearcher 实例存储在 http 缓存中。

这是我的代码:

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

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

点击 hits = searcher.Search(myQuery);

我在这里想念什么?

谢谢阅读!

4

7 回答 7

4

尝试以下操作:

protected static IndexSearcher searcher = null;
...

if (searcher == null)
{
    searcher = new IndexSearcher(jobIndexFolderPath);
}
于 2009-06-15T15:06:21.303 回答
1

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

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

于 2009-06-14T21:23:12.817 回答
1

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

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

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

于 2009-06-16T10:09:00.880 回答
0

两件事情:

  1. 如果您使用的是 .Net 2.0 并且尚未应用 SP1,可能会有所帮助。
  2. 看看这个人遇到的问题。

这两个条目都指缓存中的对象过早过期——在这两种情况下几乎都是立即过期。由于缓存中的对象不是线程安全的,事情也可能变得复杂。

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

于 2009-06-12T15:34:49.927 回答
0

我的快速回答是...

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

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

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

于 2009-06-14T21:11:06.980 回答
0

史蒂夫,请参阅使用 IndexSearcher 的最佳方式。这有点过时了,但原则仍然存在:使用 IndexSearcher 的单个实例,使用正确的线程安全代码(我不知道如何在 .Net 中执行)保护它,并在索引更新后使其无效。我相信这是 Jesse 的建议,我支持这个想法。

于 2009-06-16T11:37:36.537 回答
0

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

如果多个请求正在访问 Web 服务器进行搜索,这个逻辑/代码是否有意义 wrt 优化的搜索查询响应?

谢谢阅读。

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;

        }
于 2009-06-18T18:48:47.957 回答