user3701803
user3701803

Reputation: 93

searchAfter in lucene

I am trying out a deep search in lucene for my resources.

        Query q1 = new MultiFieldQueryParser(new String[] { "products",
                "name"}, analyzer).parse(queryStr1);
        Query q2 = new TermQuery(new Term("keywords", queryStr2));
        IndexReader ir = DirectoryReader.open(indexLocation);
        IndexSearcher is = new IndexSearcher(ir);
        TopScoreDocCollector collector = TopScoreDocCollector.create(
                reqHits, true);

        is.search(q1, collector);
        ScoreDoc results[] = collector.topDocs().scoreDocs;
        TopDocs topDocs = null;
        for (ScoreDoc scoreDoc : results) {
            topDocs = is.searchAfter(scoreDoc, q2, 1);
        }
        ScoreDoc deepResults[] = topDocs.scoreDocs;
        for (int i = 0; i < deepResults.length; i++) {
            Document doc = is.doc(deepResults[i].doc);
            System.out.println(doc.get("name"));
        }

searchAfter() can be applied on scoreDocs of a previous search.But it requires scoreDoc as the first parameter, so I loop inorder to achieve the individual scoreDoc. I am not sure how we can apply the afterSearch to get the results as expected since my code doesnt give me expected results. Thanks in advance.

Upvotes: 0

Views: 623

Answers (2)

femtoRgon
femtoRgon

Reputation: 33341

There are a couple of ways to search for results of q2 within the results of q1.

The simplest, is just combine the two queries with a boolean query:

BooleanQuery finalQuery = new BooleanQuery();
finalQuery.add(q1, BooleanClause.Occur.MUST);
finalQuery.add(q2, BooleanClause.Occur.MUST);
is.search(finalQuery, collector);

Even if your use case is to get and display results from q1, and then take q2 as input from the user, and run another search, keeping q1, and generating a BooleanQuery as the the final query remains a good approach.

You could also use a Filter for one of the queries. This is particularly useful if one of them, say q1, is a query you expect to reuse frequently, and would benefit from caching the results of it, such as:

Filter q1Filter = new CachingWrapperFilter(new QueryWrapperFilter(q1));
is.search(q2, q1Filter, collector);

Upvotes: 0

Marko Topolnik
Marko Topolnik

Reputation: 200158

This is wrong usage of searchAfter. The idea is to make one search with an upper bound on the result size, then repeat the search with searchAfter, passing the last scoreDoc from the previous result, so you get the next "result page". This is how Lucene supports unbounded result set sizes.

Upvotes: 1

Related Questions