2009-01-02 165 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運行這些結果?

做空間查詢的另一個主要好處是,你可以很容易地按距離排序你的結果,這對你的客戶是一個勝利。