Sun Java logo     Previous      Contents      Index      Next     

Sun logo
Sun Java System Portal Server 6 2004Q2 Developer's Guide 

Chapter 26
Using Java To Access the Search Server Database

You can use the search engine Java SDK to write Java programs that interface with the sendrdm program to retrieve information from the search engine database.

The chapter contains the following sections:


Creating a Search Object

The entry point for submitting searches is the Search class. You need to create a new Search object, then call doQuery() on it to execute the search query.

The first thing you need to do is create a new Search object. The full constructor syntax is:

public Search(

    String scope

    String viewAttributes,

    String viewOrder,

    int firstHit,

    int viewHits,

    String queryLanguage,

    String database,

    String RDMServer,

    String ssoToken,

)

The arguments for the constructor are outlined in the following table:

String scope

The query string or scope, that is, the string being searched for.

String viewAttributes

A comma-delimited list of the SOIF attributes to be retrieved from the database, such as URL, Author, Description. For example, score,url,title,description,classification.

String viewOrder

The order by which to sort the results. This is a comma-delimited list of attributes. Use the minus sign to indicate descending order, and a plus sign to indicate ascending order. For example, -score,+title.

int firstHits

The hit number of the first result to return. A typical value is 1.

int viewHits

Maximum number of results to return. A typical value is 10.

String queryLanguage

The Search Server query language. You should use search for a normal query.

String database

The logical name of a database (or collection) you wish to search. A typical value is null which will search the server’s default database.

String RDMServer

The URL of the search engine servlet. This argument has the form:

http://hostname.domain.com:port/portal/search

For example, if the search server is installed on www.yourcompany.com on port 80, the value would be:

http://www.yourcompany.com:80/portal/search

String ssoToken

An Sun Java System Identity Server software single sign on token used when doing secure searches. There is also a simpler convenience constructor with the following syntax:

public Search(String scope, String RDMServer)

When this constructor is used the following values are used for the unspecified arguments:

viewAttributes: null. Return all attributes.

viewOrder: null. Use the server default sort order - sorted by relevance.

firsthit: 1. Start hits at hit number 1.

viewhits: 10. Return 10 hits only.

query language: search. Search for documents using the normal query language.

database: null. Search the server’s default database.

ssoToken: null. Use anonymous search.


Executing A Query and Getting the Results

You submit a query by calling the doQuery() method.

public void doQuery()

The results from Search.doQuery() can be obtained as a SOIF stream using Search.getResultStream(). The next search will replace the previous result stream reference, so you must process the results or save a reference to the result stream after each query. There are also methods for checking the number of results.

public SOIFInputStream getResultStream()

The function getResultStream() returns a SOIFInputStream which is used to read the SOIF hit objects. Each SOIF object read from the stream corresponds to one result.

public int getHitCount()

The function Search.getHitCount() returns the number of hits that matched the query.

public int getResultCount()

The function Search.getResultCount() returns the number of results that were returned by the server. The result count will be equal to the number requested by the viewHits argument whenever there are enough results available.

public int getDocumentCount()

The function Search.getDocumentCount() returns the total number of documents searched across. This will usually equal the total number of documents in the searched database.


Working Through An Example Search Application

This section discusses the SearchDemo example application provided with the Java search SDK. The purpose of this example is to show how to use a Search object to submit a query to the search server and how to extract the results from the Search object. The example application is very simple, and limits use of Java to achieving the goals of the example. It creates a Java applet that presents the user with a text field in which to enter a search query, and a Search button to initiate the search. The results of the query are read from a SOIFInputStream returned by the Search object. The query results are displayed to standard output as plain text.

Import the Necessary Classes

In your favorite editor or Java development environment, view the search SDK file SearchDemo.java. This demo runs as a stand alone application or as an applet. The soif package is provided as part of the Search Server Java SDK, while java.applet, java.awt, and java.io are standard Java packages.

package com.sun.portal.search.demo;

import com.sun.portal.search.soif.*;

import java.applet.Applet;

import java.awt.*;

import java.io.*;

Define the SearchDemo Class

The class SearchDemo is an applet, so it extends the class Applet. SearchDemo defines init() and main() methods which allow it to run as an applet or as a stand alone (command line) program.

Code Example 26-1  SearchDemo  

/**

* Applet/application for simple query interface. Can be used as an

* example for those who want to create their own java interface.

* This example demonstrates search only. Browse, determining

* the schema of the search server and obtaining the taxonomy

* of the search server will be demonstrated in other examples.

*/

public class SearchDemo extends Applet {

    /** Run as an applet. */

    public void init() {

        String rdm = getParameter("RDMServer");

        SimpleSearch ss = new SimpleSearch(rdm);

        SearchPanel sp = new SearchPanel(ss);

        setLayout(new FlowLayout(FlowLayout.CENTER));

        add(sp);

    }

    /** Run as an application. */

    public static void main(String argv[]) throws Exception {

        int args = argv.length;

        String SOIFOutputFile = null;

        if (args != 1 && args != 2 && args != 3) {

            System.out.println("args: RDMServer [query]

            [soif_output_file_name]");

            return;

        }

        String rdm = argv[0]; // rdm search server, eg,

        // http://portal.siroe.com:2222/ps/search

        SimpleSearch ss = new SimpleSearch(rdm);

        if (args == 3) {

            --args;

            ss.setSOIFfile(argv[2]); // dump raw soif results to this file

        }

        if (args == 1) {

            // run from a search box

            Frame f = new Frame();

            SearchPanel sp = new SearchPanel(ss);

            f.add(sp);

            f.pack();

            f.show();

        }

        else {

            // run from command line

            String query = argv[1];

            ss.doSearch(query);

        }

    }

}

There is a helper class called SearchPanel which handle the applet GUI. It sets up a search panel with a text box to enter a query and a submit button to run the query. See the source file for more details.

Define the SimpleSearch Class

Notice the private helper class SimpleSearch. This is where the search is set up and executed and we will look at it in more detail here. The applet/command line class SearchDemo sets up the arguments for SimpleSearch using either applet or command line parameters. It then calls the SimpleSearch.doSearch(String scope) method to execute the search and display the results. The SimpleSearch constructor takes the location of the search server as an argument. In this way, a single SimpleSearch object can be used repeatedly to run searches against the remote search server.

The SimpleSearch.setSOIFfile(String filename) method is used by the main program to direct search results to a file when running in command line mode.

Code Example 26-2  SimpleSearch Class  

/** Performs a simple search and displays its results. */

class SimpleSearch {

    String RDMServer;

    String SOIFOutputFile;

    /**

    * SimpleSearch constructor

    * @param rdm - the rdm search server, eg, http://portal.siroe.com:2222/portal/search

    */

    public SimpleSearch(String rdm) {

        System.out.println("Sun Java System Search Java Demo");

        RDMServer = rdm;

    }

    /**

    * @param filename - a file to dump raw SOIF results into - only

    * use if running from the comand line or an applet with file

    * system access

    */

    public void setSOIFfile(String filename) {

        SOIFOutputFile = filename;

    }

    /** Execute a search */

    public void doSearch(String scope) throws IOException {

        ...see Code Example 26-3...

    }

}

Before submitting the search, SimpleSearch needs to create a Search object. The constructor for the Search class takes several arguments as discussed previously.

Code Example 26-3  doSearch Class  

/** Execute a search */

public void doSearch(String scope) throws IOException {

    /* The Search class encapsulates the search.

    ** It’s parameters are:

    ** 1) the search string

    ** 2) the attributes you want returned, comma delimited

    ** 3) sort order, comma delimited, - descending, + ascending

    ** 4) first hit

    ** 5) number of hits

    ** 6) query language, eg search, taxonomy-basic, schema-basic, etc

    ** 7) database to search

    ** 8) The RDM server URL, eg, http://portal.siroe.com:2222/ps/search

    ** 9) Access token (null for anonymous access, or valid iPlanet Directory Server Access Management Edition session id)

    */

    Search search = new Search(

        scope,

        "score,url,title,description",

        "-score",

        1,

        20,

        "search",

        null,

        RDMServer,

        null

    );

The Search constructor arguments used here are:

scope

The search scope is the actual query run by the search server. It is the scope argument to doSearch() and ultimately derives from either the applet input panel or a command line argument to the main program.

viewAttributes = "score,url,title,descri ption"

The requested attribute set shown here will result in the server returning the score, url, title, and description of all documents that match the query.

viewOrder = "-score"

A comma delimited list of the attributes to be used to sort the results. A minus sign indicates descending order, a plus sign indicates ascending order. In this case, sort the results by decreasing numerical score value, and use alphabetical order of the title as the secondary sort order.

firstHit = 1

The hit number of the first returned result.

viewHits = 20

The maximum number of results to return.

queryLanguage = "search"

The search server query language. Use search for normal searches.

RDMServer

The URL of the remote search engine, specified as an argument to the SimpleSearch constructor.

ssoToken = null

The Identity Server software single sign on token. Not used in this case, implying anonymous search.

Execute the Search Query

An output stream is created to hold the search results and paginate through the search results for a fixed number of pages, in this case five pages in total, where each page has viewHits (=20) results. The first page starts with the first hit (firstHit=1). The search is executed again for each page of results. It is possible to cache the results for all pages with a single search of course, but it is often easier to simply resubmit the search each time. This is equivalent to a user clicking a next button in a search user interface.

/* Execute the query. */

System.out.println("\nSearch results for '" + scope + "'");

DataOutputStream sos = null;

if (SOIFOutputFile != null) {

try {

sos = new DataOutputStream(new FileOutputStream(SOIFOutputFile));

}

catch (Exception e1) {

System.out.println("Error: failed to create output file: " + e1);

}

}

int pagenum = 1;

int pagesize = 10;

SOIFBuffer firstPageSOIF = new SOIFBuffer();

for (; pagenum <= 5; pagenum++) {

int firstHit = (pagenum-1)*pagesize+1;

try {

search.doQuery(firstHit, pagesize);

}

catch (Exception ex) {

ex.printStackTrace();

break;

}

// Check the result count. -1 indicates an error.

if (search.getResultCount() <= 0)

break;

The results are stored in the Search object. Now do something with the results. The functions doSomethingWithResults() and displayHTMLResults() will be defined in this file. They each show a different way of extracting the results from the Search object.

Display the Results

The example application displays the query results to standard output or to a named file. In reality, you would do more with the results than just print them like this, but once you know how to get the results out of the Search object, it is up to you what you do with them. You can use standard Java functionality to process the results in any way you like.

The Search object has a method called getResultStream() that returns a SOIFInputStream object. Each result is read from this SOIF stream in turn. Note that the client server connection uses an efficient streamed protocol; it is conceivable that the server is still returning later results while the client is processing the first results. For each SOIF object read from the result stream you can use the getValue() method to get the value of a particular field, for example, getValue("title") gets the title of a SOIF object.

First, print out some general result information:

System.out.println("=========================================");

System.out.println("page " + pagenum

+ ": hits " + search.getFirstHit()

+ " to " + (search.getFirstHit() + search.getResultCount() - 1)

+ " out of " + search.getHitCount()

+ " across " + search.getDocumentCount() + " documents");

System.out.println("=========================================");

System.out.println();

Now, retrieve each search hit from the result stream as SOIF objects and print its URL, title, description, and score to the output stream (either the Java console, standard output, or a named output file).

SOIFInputStream resultStream = search.getResultStream();

SOIF soif;

/* Examine the results of the search. The following

* code loops through the stream of SOIF instances. */

for (soif = resultStream.readSOIF(); soif != null; soif = resultStream.readSOIF()) {

    // For illustration, dump out the entire SOIF on the first page only.

    if (pagenum == 1)

        firstPageSOIF.write(soif.toByteArray());

        /* Now we use the getValue() method to get

        * the values of each of the requested

        * attributes. URL is special and has

        * its own accessor method.

        */

        String u = soif.getURL();

        String t = soif.getValue("title");

        String d = soif.getValue("description");

        String sc = soif.getValue("score");

        /* do something with the results */

        System.out.println(

            "TITLE: " + t + "\n" +

            "URL: " + u + "\n" +

            "SCORE: " + sc + "\n" +

            "DESCRIPTION: " + d + "\n" +

            "--------------------------------------------\n"

        );

        // If there is a SOIF output file, write the SOIF data there too...

        if (sos != null) {

            try {

                sos.writeBytes(soif.toString());

            }

            catch (Exception e1) {

                System.out.println("Error: failed to write to SOIF

                output file: " + e1);

            }

        }

    }

    // Break if the largest requested hit has been displayed

    if (search.getHitCount() <= (firstHit + pagesize - 1))

        break;

    }

    if (firstPageSOIF == null)

        System.out.println("No matching documents found.");

    }



Previous      Contents      Index      Next     


Copyright 2004 Sun Microsystems, Inc. All rights reserved.