Apache Lucene Query Iterate through all queries / terms

Viewed 162

I have an interface that enforces implementing classes to define and implement a function that returns an org.apache.lucene.search.Query. These classes create various queries like TermQuery, PhraseQuery, etc. Is it possible to take the org.apache.lucene.search.Query that gets returned and iterate over all of the queries and terms it's comprised of?

public interface BaseQuery {

    public Query getQuery();

    default Query toQuery() {
        Query query = getQuery();
        // iterate through Query and do things to each term
        return query;
    }
}
public class ContainsQuery implements BaseQuery {
    
    @Override
    protected Query getQuery() {
        PhraseQuery.Builder queryBuilder = new PhraseQuery.Builder();
        queryBuilder.add(new Term("field", "value");
        return queryBuilder.build();
    }
}
2 Answers

As you can't update the changes (setTerms or similar), not even in this implementation (PhraseQuery), maybe this works.

You could first retrieve them, and loop over them. Whatever modification you wish to do, update the term or create a new one, or even discard those unwanted.

Then, assign query to a newly constructed object with the modified terms. Something like a manual update/set for a Query object. In the example I just add the terms to the builder, but you could include the previous parameters as well (slop, ...).


default Query toQuery() 
{
    Query query = getQuery();
    Term[] terms= query.getTerms();
    List<Term> modifiedTerms = new ArrayList<>();
    for (Term t : terms)
    {
        /*Your modifications here f.e --> you copy one, create two terms and discard one
         Term toAdd=null;
         toAdd= t.clone();
         ...
         toAdd = new Term((t.field()+"suffix"), t.text());
         ...
         toAdd = new Term("5","6"); 
         ...
         (do nothing-discard)

         if (toAdd!=null)
            modifiedTerms.add(toAdd);*/
    }
    
    PhraseQuery.Builder builder = new PhraseQuery.Builder();
    for (int i=0;i<modifiedTerms.size();i++)
         builder.add(modifiedTerms.get(i),i);
    
    query = builder.build();  
    return query;                               
} 
       /* override the reference and assign a new one very similar to s 
         set/update, if those where implemented.                               
          The last query will be erased on the next GC 
          so there's not a big gap here. Also this is most surely 
          a not needed micro-optimization, no worries. */

The way to do this is using the QueryTermExtractor.

WeightedTerm[] terms = QueryTermExtractor.getTerms(query);

for (WeightedTerm term : terms) {
    System.out.println("THE TERM: " + term.getTerm());
}

The issue I was having is that all examples I found were calling .getTerms() on a org.apache.lucene.search.Query but .getTerms() seems to no longer be implemented on the base Query class.

Also, @aran's suggested approach of constructing a new Query object is an appropriate method to "modifying" the terms on an already constructed immutable Query object.

Related