Menangani Hasil Penelusuran

Jika panggilan kueri selesai secara normal, panggilan akan menampilkan hasilnya sebagai objek Results. Objek Hasil memberi tahu Anda jumlah dokumen yang cocok yang ditemukan dalam indeks, serta jumlah dokumen yang cocok yang ditampilkan. Daftar ini juga menyertakan koleksi ScoredDocuments yang cocok. Koleksi biasanya berisi sebagian dari semua dokumen yang cocok yang ditemukan, karena penelusuran menampilkan jumlah dokumen yang terbatas setiap kali dipanggil. Dengan menggunakan offset atau kursor, Anda dapat mengambil semua dokumen yang cocok, satu subset setiap kalinya.

Hasil

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

Bergantung pada nilai opsi kueri limit, jumlah dokumen yang cocok yang ditampilkan dalam hasil mungkin kurang dari jumlah yang ditemukan. Ingatlah bahwa jumlah yang ditemukan akan berupa perkiraan jika jumlah yang ditemukan memiliki akurasi lebih kecil dari jumlah yang ditemukan. Terlepas dari cara Anda mengonfigurasi opsi penelusuran, panggilan search() tidak akan menemukan lebih dari 10.000 dokumen yang cocok.

Jika dokumen yang ditemukan lebih banyak daripada yang ditampilkan dan Anda ingin mengambil semuanya, Anda perlu mengulangi penelusuran menggunakan offset atau kursor, seperti yang dijelaskan di bawah ini.

Dokumen yang diberi skor

Hasil penelusuran akan menyertakan Kumpulan ScoredDocuments yang cocok dengan kueri. Anda dapat mengambil kumpulan menggunakan metode getResults() atau melakukan iterasi pada anggotanya langsung dari hasil penelusuran itu sendiri. Kedua metode tersebut ditampilkan di sini:

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

Secara default, dokumen yang diberi skor berisi semua kolom dokumen asli yang diindeks. Jika opsi kueri Anda menyertakan setFieldsToReturn, hanya kolom tersebut yang akan muncul dalam hasil saat Anda memanggil getFields() di dokumen. Jika Anda menggunakan addExpressionToReturn atau setFieldsToSnippet untuk membuat kolom komputasi, ambil keduanya secara terpisah dengan memanggil getExpressions() pada dokumen.

Menggunakan offset

Jika penelusuran Anda menghasilkan lebih banyak dokumen daripada yang dapat dikembalikan sekaligus, gunakan offset untuk mengindeks ke dalam daftar dokumen yang cocok. Misalnya, batas kueri default adalah 20 dokumen. Setelah Anda menjalankan pencarian untuk pertama kalinya (dengan offset 0) dan mengambil 20 dokumen pertama, ambil 20 dokumen berikutnya dengan mengatur offset menjadi 20 dan jalankan kembali pencarian yang sama. Terus ulangi penelusuran, dengan menambah offset setiap kali dengan jumlah dokumen yang ditampilkan:

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

Offset bisa menjadi tidak efisien saat melakukan iterasi pada kumpulan hasil yang sangat besar.

Menggunakan kursor

Anda juga dapat menggunakan kursor untuk mengambil subrentang hasil. Kursor berguna ketika Anda bermaksud untuk mempresentasikan hasil penelusuran di halaman yang berurutan dan ingin memastikan Anda tidak melewatkan dokumen apa pun jika indeks dapat dimodifikasi di antara kueri. Kursor juga lebih efisien saat melakukan iterasi pada kumpulan hasil yang sangat besar.

Untuk menggunakan kursor, Anda harus membuat kursor awal dan menyertakannya dalam opsi kueri. Ada dua jenis kursor, per kueri dan per hasil. Kursor per kueri menyebabkan kursor terpisah dikaitkan dengan objek hasil yang ditampilkan oleh panggilan penelusuran. Kursor per hasil menyebabkan kursor dikaitkan dengan setiap dokumen yang diberi skor dalam hasil.

Menggunakan kursor per kueri

Secara default, kursor yang baru dibuat adalah kursor per kueri. Kursor ini menyimpan posisi dokumen terakhir yang ditampilkan di hasil penelusuran. Data ini diperbarui dengan setiap penelusuran. Untuk menghitung semua dokumen yang cocok dalam indeks, jalankan penelusuran yang sama hingga hasilnya menampilkan kursor 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...
}

Menggunakan kursor per hasil

Untuk membuat kursor per hasil, Anda harus menetapkan properti perResult kursor ke benar (true) saat membuat kursor awal. Saat penelusuran ditampilkan, setiap dokumen akan memiliki kursor yang terkait dengannya. Anda dapat menggunakan kursor tersebut untuk menentukan penelusuran baru dengan hasil yang dimulai dengan dokumen tertentu. Perhatikan bahwa saat Anda meneruskan kursor per hasil ke penelusuran, tidak akan ada kursor per kueri yang dikaitkan dengan hasil itu sendiri; result.getCursor() akan menampilkan null sehingga Anda tidak bisa menggunakannya untuk menguji apakah Anda telah mengambil semua kecocokan.

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

Menyimpan dan memulihkan kursor

Kursor dapat diserialisasi sebagai string yang aman bagi web, disimpan, lalu dipulihkan untuk digunakan nanti:

String cursorString = cursor.toWebSafeString();
// Save the string ... and restore:
Cursor cursor = Cursor.newBuilder().build(cursorString));