검색결과 처리

쿼리 호출이 정상적으로 완료되면 결과가 Results 객체로 반환됩니다. 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...
}

매우 큰 결과 집합에 대해 반복하는 경우에는 오프셋이 비효율적일 수 있습니다.

커서 사용

커서를 사용하여 결과의 하위 범위를 검색할 수도 있습니다. 커서는 검색 결과를 연속된 페이지에 표시하고 쿼리 사이에 색인을 수정하더라도 문서를 건너뛰지 않으려는 경우에 유용합니다. 커서는 매우 큰 결과 집합에서 반복할 때도 효율적입니다.

커서를 사용하려면 초기 커서를 만들어 쿼리 옵션에 포함시켜야 합니다. 커서 종류에는 쿼리별 커서와 결과별 커서 등 두 가지가 있습니다. 쿼리별 커서를 사용하면 별도의 커서가 검색 호출로 반환된 결과 객체와 연결됩니다. 결과별 커서를 사용하면 커서가 결과에 있는 모든 점수가 매겨진 문서와 연결됩니다.

쿼리별 커서 사용

기본적으로 새로 생성되는 커서는 쿼리별 커서입니다. 이 커서는 검색 결과에서 반환된 마지막 문서 위치를 기억합니다. 검색할 때마다 위치가 업데이트됩니다. 일치하는 모든 문서를 하나의 색인에 열거하려면 결과가 null 커서를 반환할 때까지 동일한 검색을 실행합니다.

// 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...
}

결과별 커서 사용

결과별 커서를 만들려면 초기 커서 생성 시 cursor perResult 속성을 true로 설정해야 합니다. 검색이 반환될 때 문서마다 연결된 커서가 생깁니다. 해당 커서를 사용하여 특정 문서로 시작되는 결과로 새로운 검색을 지정할 수 있습니다. 결과별 커서를 검색에 전달할 때는 결과 자체와 연결된 쿼리별 커서는 없습니다. 즉, result.getCursor()가 null을 반환하므로, 이 메서드를 사용하여 모든 일치 항목을 가져왔는지 여부를 테스트할 수 없습니다.

// 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));