2

我创建了一个示例 Lucene 代码片段,它索引一个小文件。我能够正确执行索引并搜索单个字段值。但是,我想查询多个字段。我正在使用BooleanQuery,但它不起作用。

有人可以建议吗?这是我的代码片段。

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

这是data.txt我正在使用的。

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
4

2 回答 2

3

终于让那个东西工作了。以下是您应该如何使用它。

  1. BooleanQuery使用您的字段和参数构建您的查询。
  2. 使用 .传递BooleanQuery要解析的字符串QueryParser

这是相同的片段。

BooleanQuery b = new BooleanQuery();

Set<String> fields = params.keySet();
StandardAnalyzer analyzer = new StandardAnalyzer(version);

b.add(new TermQuery(new Term("cs-method", "GET"), BooleanClause.Occur.SHOULD);
b.add(new TermQuery(new Term("cs-uri", "/blank"), BooleanClause.Occur.SHOULD);

Query q = new QueryParser(version, "cs-method", analyzer).parse(b.toString());
于 2012-08-03T08:00:30.060 回答
1

这是main()上面代码片段下方的方法:

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

此外,输出如下:

Total Number of Documents - 11
Total Clues Found - 0

QueryParser和的查询不同BooleanQuery。我在另一个版本中看到了一个没有的+标志。QueryParser检查以下内容。

使用QueryParser

Query q = new QueryParser(version, "cs-method", new StandardAnalyzer(version)).parse("cs-method:GET AND cs-uri:/blank");

输出为QueryParser

Total Number of Documents - 11
Query --> +cs-method:get +cs-uri:blank
Total Clues Found - 5

使用BooleanQuery

Map<String, String> searchParams = new HashMap<String, String>();
searchParams.put("cs-method", "GET");
searchParams.put("cs-uri", "/blank");
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);
}

输出为BooleanQuery

Total Number of Documents - 11
Query --> cs-method:GET cs-uri:/blank
Total Clues Found - 0
于 2012-07-19T18:03:19.407 回答