I have the created a sample Lucene code snippet which indexes a small file. I am able to perform the indexing correctly and search on a single field values. But, I want to query on multiple fields. I am using BooleanQuery, but it’s not working.
Can somebody suggest? Here is my code snippet.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;
public class LocalFSLucene {
private final Version version = Version.LUCENE_36;
private final String indexDirectory = "/Work/Lucene/LocalFSIndex";
private final String dataFile = "/Work/Lucene/data.txt";
private final String fields[] = {"date", "time", "cs-method", "cs-uri",
"sc-status", "time-taken"};
private IndexWriterConfig config = null;
public void setConfig() {
/* Check if the IndexWriterConfiguration is available or not.
* If not, we will create one and save it for any further references.
*/
if (config == null) {
config = new IndexWriterConfig(version, new StandardAnalyzer(version));
}
}
private final String rowDelimiter = " ";
public void buildIndex() throws Exception {
/* Create the Configuration object for writing index files */
setConfig();
/* Get the handle to the directory where indexes will be created */
Directory dir = new SimpleFSDirectory(new File(indexDirectory));
/* Initialize the index writer object */
IndexWriter indexWriter = new IndexWriter(dir, config);
/* Reader object to read the data file */
BufferedReader reader = new BufferedReader(new FileReader(dataFile));
/* Read each line of the data and build the index on the fields */
String row = null;
while ((row = reader.readLine()) != null) {
/* Get each field in the current row */
String fieldValues[] = row.split(rowDelimiter);
/* Create a document for each row to store the index information */
Document doc = new Document();
for (int i = 0; i < fields.length; i++) {
doc.add(new Field(fields[i], fieldValues[i], Field.Store.YES, Field.Index.ANALYZED));
}
/* Add the document to index */
indexWriter.addDocument(doc);
}
/* Push the index files on the File System */
indexWriter.commit();
/* Close the reader object */
reader.close();
/* Close the index writer object */
indexWriter.close();
System.out.println("Indexing is complete");
}
public void search(Map<String, String> params) throws Exception {
/* Get the handle to the directory where indexes are be created */
Directory dir = new SimpleFSDirectory(new File(indexDirectory));
/* Create the Index Reader object to read the indexes created */
IndexReader reader = IndexReader.open(dir);
/* Create the detective object which will perform search operation */
IndexSearcher detective = new IndexSearcher(reader);
System.out.println("Total Number of Documents - " + detective.maxDoc());
/* Build the query containing the clues which the detective will use
* to solve the case.
*/
//Query q = new QueryParser(version, field, new StandardAnalyzer(version)).parse(value);
BooleanQuery q = new BooleanQuery();
Set<String> fields = params.keySet();
for (String field : fields) {
q.add(new TermQuery(new Term(field, params.get(field))), BooleanClause.Occur.SHOULD);
}
/* The TopScoreDocCollector will create the bag where the detective will
* put all the found clues to solve the case.
*/
TopScoreDocCollector clueBag = TopScoreDocCollector.create(10, true);
/* Ask the detective to start */
detective.search(q, clueBag);
/* Get all the clues which the detective found during investigation
* and display them.
*/
ScoreDoc clues[] = clueBag.topDocs().scoreDocs;
System.out.println("Total Clues Found - " + clues.length);
System.out.println();
for (int i = 0; i < clues.length; i++) {
/* Get the pointer to the clue */
int clueId = clues[i].doc;
/* Get the actual clue from the clue bag */
Document clue = detective.doc(clueId);
/* Print the document */
List<Fieldable> lstFields = clue.getFields();
System.out.print((i + 1) + " --> ");
for (Fieldable fld : lstFields) {
String strField = fld.name();
String strValue = clue.get(strField);
System.out.print(strField + ":" + strValue + " ");
}
System.out.println();
}
}
public static void main(String args[]) throws Exception {
LocalFSLucene obj = new LocalFSLucene();
//obj.buildIndex();
Map<String, String> searchParams = new HashMap<String, String>();
searchParams.put("cs-method", "GET");
searchParams.put("cs-uri", "/blank");
obj.search(searchParams);
}
}
Here is the data.txt which I am using.
2010-04-21 02:24:01 GET /blank 200 120
2010-04-21 02:24:01 GET /US/registrationFrame 200 605
2010-04-21 02:24:02 GET /US/kids/boys 200 785
2010-04-21 02:24:02 POST /blank 304 56
2010-04-21 02:24:04 GET /blank 304 233
2010-04-21 02:24:04 GET /blank 500 567
2010-04-21 02:24:04 GET /blank 200 897
2010-04-21 02:24:04 POST /blank 200 567
2010-04-21 02:24:05 GET /US/search 200 658
2010-04-21 02:24:05 POST /US/shop 200 768
2010-04-21 02:24:05 GET /blank 200 347
Finally got that thing working. Here is how you are suppose to use it.
BooleanQuerywith your fields and parameters.BooleanQueryString to be parsed using theQueryParser.Here is the snippet for the same.