2009-01-02 119 views
3

我正在使用基于web的工作搜索应用程序,在我的网站上使用Lucene.User可以搜索距离“Boston,MA”或任何其他位置100英里范围内的作业。 此外,我需要显示按照“相关性”(即由lucene返回的分数)按降序排列的搜索结果。需要Lucene查询优化建议

我使用第三方API获取城市给定半径范围内的所有城市。此API将我带回“马萨诸塞州波士顿”100英里范围内的864个城市。

我正在使用以下逻辑构建城市/州Lucene查询,这是我的“BuildNearestCitiesQuery”方法的一部分。 这里nearestcities是由上述API返回的散列表。它包含864个城市,其中CityName驴密钥和StateCode为值。 而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的搜索方法得到100方圆:

searcher.Search(finalQuery, collector); 

我发现这个BuildNearestCitiesQuery方法呈现平均高达29秒执行中的所有作业这显然是一个网站的任何标准所不能接受的。我还发现涉及“解析”的陈述与其他陈述相比需要相当多的时间来执行。

对于一个给定地点的作业是一个动态属性,意思是一个城市今天可以有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)); 

由于一吨阅读我会很感激你对这种帮助。

詹尼斯

回答

3

不太清楚,如果我完全理解你的代码,但是当涉及到地理空间搜索时,过滤方法可能更合适。也许这个链接可以给你一些想法 - http://sujitpal.blogspot.com/2008/02/spatial-search-with-lucene.html

也许你可以使用过滤器 s为您的查询的其他部分以及。说实话你的查询看起来相当复杂。

--Hardy

+0

请你看看这个和评论??谢谢。 http://stackoverflow.com/questions/1052086/spatialquery-for-location-based-search-using-lucene – user74042 2009-06-27 23:55:05

0
tempFinalQuery

除了被闲置不必要的地图查找来获得状态,似乎没有要任何东西在您发布的代码太令人震惊。除了格式化...

如果所有的时间都在Parse方法中,在这里发布他们的代码是有道理的。

0

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

+0

请你看看这个和评论??谢谢。 http://stackoverflow.com/questions/1052086/spatialquery-for-location-based-search-using-lucene – user74042 2009-06-27 23:54:18

0

我认为最好的办法是到最近的城市确定进入搜索过滤器。我也会重新考虑你是如何进行现场设置的;考虑创建一个具有城市+状态的术语,以便简化查询。

0

我建议:

  • 存储的位置的纬度和经度,因为他们进来
  • 当用户输入城市和距离,把它转换成纬度/经度值和度
  • 做基于数字距离/纬度比较

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

0

与这里的其他人一致,这种气味太多了。此外,对城市名称进行文本搜索并不总是可靠的。地名之间经常有一些主观性(特别是在一个城市内可能本身很大的地区)。

做地理空间查询是一种方法。不知道你的其他设置很难提供建议。例如,您可以将流畅的支持内置到NHibernate中,并且支持SQL Server 2008。然后,您可以快速高效地搜索非常。然而,你的挑战是在Lucene中使用这个工具。

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

做空间查询的另一个主要好处是,你可以很容易地按距离排序你的结果,这对你的客户是一个胜利。