需要Lucene查询优化建议

时间:2009-01-02 06:07:35

标签: lucene lucene.net

在我的网站上使用Lucene.User处理基于网络的工作搜索应用程序可以搜索距离“波士顿,马萨诸塞州”或任何其他位置100英里范围内的工作。 另外,我需要按降序显示按“相关性”排序的搜索结果(即lucene返回的分数)。

我正在使用第三方API来获取城市给定半径范围内的所有城市。这个API让我回到“波士顿,马萨诸塞州”方圆100英里范围内的864个城市。

我正在使用以下逻辑构建城市/州Lucene查询,该逻辑是我的“BuildNearestCitiesQuery”方法的一部分。 这里的nearestCities是上述API返回的哈希表。它包含864个城市,其中CityName为ass键,StateCode为value。 finalQuery是一个Lucene BooleanQuery对象,它包含用户输入的其他搜索条件,如:技能,关键字等。

foreach (string city in nearestCities.Keys)

{

    BooleanQuery tempFinalQuery = finalQuery;

    cityStateQuery = new BooleanQuery();    

    queryCity = queryParserCity.Parse(city);

    queryState = queryParserState.Parse(((string[])nearestCities[city])[1]);

    cityStateQuery.Add(queryCity, BooleanClause.Occur.MUST); //must is like an AND

    cityStateQuery.Add(queryState, BooleanClause.Occur.MUST);

} 


nearestCityQuery.Add(cityStateQuery, BooleanClause.Occur.SHOULD); //should is like an OR



finalQuery.Add(nearestCityQuery, BooleanClause.Occur.MUST);

然后我将finalQuery对象输入Lucene的Search方法,以获得100英里范围内的所有作业。

searcher.Search(finalQuery, collector);

我发现这个BuildNearestCitiesQuery方法平均需要花费29秒才能执行,这显然是网站的任何标准所不能接受的。我还发现涉及“Parse”的语句需要相当长的时间来执行与其他陈述相比。

对于给定位置的作业是动态属性,在某种意义上,城市今天可以有2个作业(满足特定的搜索条件),但是在3天后对于相同的搜索条件没有作业。所以,我不能使用任何在这里“缓存”。

我有什么方法可以优化这种逻辑吗?或者就我的整个方法/算法而言,使用Lucene找到100英里范围内的所有工作?

仅供参考,这是我在Lucene的索引的样子:

doc.Add(new Field("jobId", job.JobID.ToString().Trim(), Field.Store.YES, Field.Index.UN_TOKENIZED));

doc.Add(new Field("title", job.JobTitle.Trim(), Field.Store.YES, Field.Index.TOKENIZED));

doc.Add(new Field("description", job.JobDescription.Trim(), Field.Store.NO, Field.Index.TOKENIZED));

doc.Add(new Field("city", job.City.Trim(), Field.Store.YES, Field.Index.TOKENIZED , Field.TermVector.YES));

doc.Add(new Field("state", job.StateCode.Trim(), Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES));

doc.Add(new Field("citystate", job.City.Trim() + ", " + job.StateCode.Trim(), Field.Store.YES, Field.Index.UN_TOKENIZED , Field.TermVector.YES));

doc.Add(new Field("datePosted", jobPostedDateTime, Field.Store.YES, Field.Index.UN_TOKENIZED));

doc.Add(new Field("company", job.HiringCoName.Trim(), Field.Store.YES, Field.Index.TOKENIZED));

doc.Add(new Field("jobType", job.JobTypeID.ToString(), Field.Store.NO, Field.Index.UN_TOKENIZED,Field.TermVector.YES));

doc.Add(new Field("sector", job.SectorID.ToString(), Field.Store.NO, Field.Index.UN_TOKENIZED, Field.TermVector.YES));

doc.Add(new Field("showAllJobs", "yy", Field.Store.NO, Field.Index.UN_TOKENIZED));

非常感谢您的阅读!我非常感谢您的帮助。

的Janis

6 个答案:

答案 0 :(得分:3)

不完全确定我是否完全理解您的代码,但是当涉及到地理空间搜索时,过滤器方法可能更合适。也许这个链接可以为您提供一些想法 - http://sujitpal.blogspot.com/2008/02/spatial-search-with-lucene.html

也许您可以将过滤器用于查询的其他部分。说实话,你的查询看起来很复杂。

- 哈迪

答案 1 :(得分:0)

除了tempFinalQuery未被使用以及不必要的地图查找以获取状态之外,在您发布的代码中似乎没有任何太令人震惊的事情。除了格式化......

如果在Parse方法中花费了所有时间,那么在此处发布代码是有意义的。

答案 2 :(得分:0)

我可能错过了您的问题,但您是否可以存储邮政编码的纬度和经度?如果这是一个选项,那么您可以计算两个坐标之间的距离,从而提供更直接的评分指标。

答案 3 :(得分:0)

我认为最好的方法是将最近的城市决定移动到搜索过滤器中。我还会重新考虑如何进行现场设置;考虑创建一个具有city + state的术语,以便简化查询。

答案 4 :(得分:0)

我建议:

  • 存储进入的位置的纬度和经度
  • 当用户输入城市和距离时,将其转换为纬度/经度值和度数
  • 基于数字距离lat / lon比较进行单一,简单的查找

您可以在Geo::Distance Perl模块中看到一个如何工作的示例。查看source中的closest方法,该方法通过简单的SQL实现此查找。

答案 5 :(得分:0)

在这里与其他人一致认为这闻起来太多了。对城市名称进行文本搜索并不总是那么可靠。地名之间经常存在一些主观性(特别是城市中可能本身很大的区域)。

进行地理空间查询是可行的方法。不知道你的其他设置,很难建议。您可以在Fluent到NHibernate和SQL Server 2008中内置Spatial支持。然后,您可以快速有效地搜索非常。但是,您面临的挑战是如何在Lucene中实现这一目标。

您可以在SQL Server中使用空间支持进行“首次通过”查询,然后通过Lucene运行这些结果吗?

进行空间查询的另一个主要好处是,您可以轻松地按距离对结果进行排序,这对您的客户来说是一种胜利。