在我的网站上使用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
答案 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)
我建议:
您可以在Geo::Distance Perl模块中看到一个如何工作的示例。查看source中的closest
方法,该方法通过简单的SQL实现此查找。
答案 5 :(得分:0)
在这里与其他人一致认为这闻起来太多了。对城市名称进行文本搜索并不总是那么可靠。地名之间经常存在一些主观性(特别是城市中可能本身很大的区域)。
进行地理空间查询是可行的方法。不知道你的其他设置,很难建议。您可以在Fluent到NHibernate和SQL Server 2008中内置Spatial支持。然后,您可以快速有效地搜索非常。但是,您面临的挑战是如何在Lucene中实现这一目标。
您可以在SQL Server中使用空间支持进行“首次通过”查询,然后通过Lucene运行这些结果吗?
进行空间查询的另一个主要好处是,您可以轻松地按距离对结果进行排序,这对您的客户来说是一种胜利。