1. 多個MUST的組合不必多說,就是交集
2. MUST和SHOULD的組合。是在MUST搜出來的doc里面,根據SHOULD的query進行打分。也就是說,SHOULD的query不會影響最終的HITS,只會提供打分依據。
3. SHOULD的組合。如果最終的BooleanQuery只有SHOULD,那么搜出來的doc至少要滿足一個SHOULD的query,也就是說是邏輯OR。
那么在下面這段代碼中,問題就出現了:
代碼的本意是在baseQuery的基礎上和geoQuery做一個交集
public Map<String, Query> buildGeoQuery(Query baseQuery) {
Map<String, Query> queryMap = new HashMap<String, Query>();
for(String key : localHashMap.keySet()) {
List<String> hashValues = localHashMap.get(key);
BooleanQuery bq = new BooleanQuery();
bq.add(baseQuery, Occur.MUST);
if(hashValues.size() == 1) {
TermQuery hashQuery = new TermQuery(new Term(Constants.FIELD_SEARCH_HASH, hashValues.get(0)));
bq.add(hashQuery, Occur.MUST);
}
else if(hashValues.size() > 1) {
for(String value : hashValues) {
TermQuery hashQuery = new TermQuery(new Term(Constants.FIELD_SEARCH_HASH, value));
bq.add(hashQuery, Occur.SHOULD);
}
}
queryMap.put(key, bq);
}
return queryMap;
}
在第三個用紅色標注的語句中,本意是對多個geohash query做邏輯OR的操作(使用了should),但是由於最開始的basequery是以MUST關鍵字加入的,那么這些個geohash query只做為打分依據,而不是必須出現的,這樣就會導致有一些額外的doc被搜出來。
正確的做法應該是用一個獨立的GeoQuery來把geohash termquery組合起來,最后將geoQuery和baseQuery用Occur.MUST組合
===============================================================================
lucene3.0中BooleanQuery 實現與或的復合搜索 .
BooleanClause用於表示布爾查詢子句關系的類,包 括:BooleanClause.Occur.MUST,BooleanClause.Occur.MUST_NOT,BooleanClause.Occur.SHOULD。 必須包含,不能包含,可以包含三種.有以下6種組合:
1.MUST和MUST:取得連個查詢子句的交集。
2.MUST和MUST_NOT:表示查詢結果中不能包含MUST_NOT所對應得查詢子句的檢索結果。
3.SHOULD與MUST_NOT:連用時,功能同MUST和MUST_NOT。
4.SHOULD與MUST連用時,結果為MUST子句的檢索結果,但是SHOULD可影響排序。
5.SHOULD與SHOULD:表示“或”關系,最終檢索結果為所有檢索子句的並集。
6.MUST_NOT和MUST_NOT:無意義,檢索無結果。
====================================================================================
在輸入要搜索的關鍵字時,Lucene是這樣處理的:
+a +b:搜索同時包含a又包含b的結果集
a b:搜索包含a或包含b的結果集
+a -b:搜索包含a不包含b的結果集
也就是如下結論:
a & b => +a +b
a || b => a b
a !b => +a -b
那在代碼中該如何來構造這種與或非的關系呢?
一般用BooleanQuery來構造。
//構造BooleanQuery
QueryParser parser = new QueryParser("content", analyzer);
BooleanQuery bquery = new BooleanQuery();
TokenStream ts = analyzer.TokenStream(null, new StringReader(querystring));
Lucene.Net.Analysis.Token token;
while ((token = ts.Next()) != null)
{
Query query = parser.Parse(token.TermText());
bquery.Add(query, BooleanClause.Occur.MUST);
}
//構造完成
IndexSearcher searcher = new IndexSearcher("IndexDirectory");
//Query query = parser.Parse(querystring);
//輸出我們要查看的表達式
Console.WriteLine(bquery.ToString());
Hits hits = searcher.Search(bquery);
for (int i = 0; i < hits.Length(); i++)
{
Document doc = hits.Doc(i);
Console.WriteLine(doc.Get("title"));
}
}
其中,bquery.Add(query, BooleanClause.Occur.MUST);MUST構造出“與”的關系
構造“或”關系:bquery.Add(query, BooleanClause.Occur.SHOULD);
構造“非”關系:bquery.Add(query, BooleanClause.Occur.MUST_NOT);
