查詢呼叫正常完成時,會以 Results
物件的形式傳回結果。「結果」物件會告知您在索引中找到的相符文件數量,以及傳回的相符文件數量,同時也會提供與 ScoredDocuments
相符的集合。這個集合通常包含所有找到相符文件的一部分,因為搜尋會在每次呼叫時傳回限定數量的文件。您可以使用位移或游標來擷取所有相符文件 (一次一個子集)。
結果
// index and query have already been defined ...
try {
Results<ScoredDocument> result = index.search(query);
long totalMatches = result.getNumberFound();
int numberOfDocsReturned = result.getNumberReturned();
Collection<ScoredDocument> listOfDocs = result.getResults();
} catch (SearchException e) {
// handle exception...
}
視 limit
查詢選項的值而定,結果中傳回的相符文件數量可能會小於找到的數量。請注意,如果找到數量的準確率低於找到的數量,則找到的數量為預估值。無論您如何設定搜尋選項,search()
呼叫最多只會找到 10,000 個相符的文件。
如果找到的文件數量比傳回的文件多,而您想要擷取所有文件,則須如下所述使用位移或游標來重複執行搜尋。
計分文件
搜尋結果會包含符合查詢的 ScoredDocuments
集合。您可以使用 getResults()
方法擷取集合,也可以直接從搜尋結果中逐一檢視其成員。這兩種方法顯示如下:
// index and query have already been defined ...
Results<ScoredDocument> result = index.search(query);
// Grab the collection for later use:
Collection<ScoredDocument> theDocs = result.getResults();
// Alternatively, iterate over the results directly:
for (ScoredDocument doc : result) {
// do work
}
根據預設,計分文件包含已編入索引之原始文件的所有欄位。如果查詢選項已指定 setFieldsToReturn
,則當您對文件呼叫 getFields()
時,只有這些欄位會顯示在結果中。如果您使用 addExpressionToReturn
或 setFieldsToSnippet
建立運算欄位,請對文件呼叫 getExpressions()
來分別擷取這些欄位。
使用位移
如果搜尋找到的文件數量比一次可傳回的文件數量多,請使用位移將相符文件清單編入索引。例如,預設查詢上限為 20 個文件。在第一次執行搜尋 (使用位移 0) 並擷取前 20 個文件後,將位移設為 20 並再次執行相同的搜尋,即可擷取後續的 20 個文件。持續重複執行搜尋,每次均以傳回的文件數量對位移進行遞增:
// index and queryString have already been defined
try {
int numberRetrieved = 0;
int offset = 0;
do {
// build options and query
QueryOptions options = QueryOptions.newBuilder()
.setOffset(offset)
.build();
Query query = Query.newBuilder().setOptions(options).build(queryString);
// search at least once
Results<ScoredDocument> result = index.search(query);
numberRetrieved = result.getNumberReturned();
if (numberRetrieved > 0) {
offset += numberRetrieved;
// process the matched docs
}
}
while (numberRetrieved > 0);
} catch (SearchException e) {
// handle exception...
}
疊代處理非常大型的結果集時,使用位移可能會效率不彰。
使用游標
您也可以使用游標來擷取某個子範圍的結果。如果您想要以連續頁面呈現搜尋結果,並且確保在查詢之間修改索引時仍不會略過任何文件,那麼游標會是很實用的方式。疊代處理非常大型的結果集時,使用游標也可提高效率。
如要使用游標,您必須建立初始游標,並將該游標包含在查詢選項中。游標有兩種形式:「根據查詢」以及「根據結果」。「根據查詢」的游標會將個別的游標關聯至搜尋呼叫所傳回的結果物件。「根據結果」的游標會將游標關聯至結果中的每個計分文件。
使用根據查詢的游標
根據預設,新建構的游標為根據查詢的游標。這個游標會保存搜尋結果傳回的最後一個文件所在位置,這個位置會隨著每次搜尋進行更新。如要列舉索引中的所有相符文件,請執行相同的搜尋,直到結果傳回空值游標為止:
// index and queryString have already been defined
try {
// create the initial cursor
Cursor cursor = Cursor.newBuilder().build();
do {
// build options and query
QueryOptions options = QueryOptions.newBuilder()
.setCursor(cursor)
.build();
Query query = Query.newBuilder().setOptions(options).build(queryString);
// search at least once
Results<ScoredDocument> result = index.search(query);
int numberRetrieved = result.getNumberReturned();
cursor = result.getCursor();
if (numberRetrieved > 0) {
// process the matched docs
}
}
while (cursor != null);
// all done!
} catch (SearchException e) {
// handle exception...
}
使用根據結果的游標
如要建立根據結果的游標,您必須在建立初始游標時,將游標 perResult 屬性設定為 True。搜尋傳回結果時,每個文件都會有與該結果建立關聯的游標。您可以使用該游標,指定新搜尋時含有以特定文件開始的結果。請注意,當您將根據結果的游標傳送到搜尋時,不會有任何根據查詢的游標與結果本身相關聯;result.getCursor() 會傳回空值,這樣您就無法使用這種方式來測試是否已擷取所有相符項目。
// index and queryString have already been defined
try {
// create an initial per-result cursor
Cursor cursor = Cursor.newBuilder().setPerResult(true).build();
// build options and query
QueryOptions options = QueryOptions.newBuilder()
.setCursor(cursor)
.build();
Query query = Query.newBuilder().setOptions(options).build(queryString);
Results<ScoredDocument> result = index.search(query);
// process the matched docs
cursor = null;
for (ScoredDocument doc : result) {
// discover some document of interest and grab its cursor
if (...)
cursor = doc.getCursor();
}
// Start the next search from the document of interest
if (cursor != null) {
options = QueryOptions.newBuilder()
.setCursor(cursor)
.build();
query = Query.newBuilder().setOptions(options).build(queryString);
result = index.search(query);
}
} catch (SearchException e) {
// handle exception
}
儲存和還原游標
您可將游標序列化為網頁安全字串並加以儲存,然後還原以供日後使用:
String cursorString = cursor.toWebSafeString();
// Save the string ... and restore:
Cursor cursor = Cursor.newBuilder().build(cursorString));