Page tree
Skip to end of metadata
Go to start of metadata

Overview

An incoming  QueryRequest  contains a QueryString  that is parsed into a Query  object by the queryParser component of the queryInit workflow.  Once the Query object is instantiated, we can operate on it through the Query Model to modify the query in simple or sophisticated ways though the business logic of a special query transformer. 


Applications for query modification include (but are not limited to):

  • Applying custom business logic by converting user queries to joins, etc.
  • Inspecting queries for debugging.
  • Applying relevancy/tuning to incoming queries (setting/changing boosts, applying field to user query, etc.).
  • Applying custom linguistic transformations.

The incoming query can be augmented, limited, and changed in any way. Modifications can take three forms:

  • In-place modifications – query is modified and returned.
  • Query replacement – new query is constructed and returned from rewriteQuery().
  • Query deletion – null is returned from rewriteQuery().

Related Pages

The following pages contain information that is especially relevant to this topic:

 

View incoming links.

ModifyQueryTransformer

The example code on this page is attached as ModifyQueryTransformer.java.

Nodes in the query tree can be modified by implementing QueryTraverser.rewriteQuery().

The ModifyQueryTransformer example applies a QueryTraverser  to a Query.  This example demonstrates several different QueryTransformer instantiations.  To switch from one to another, call a different constructor at the beginning of the processQuery() method.


This is the ModifyQueryTransformer definition:

ModifyQueryTransformer.xml
 class ModifyQueryTransformer implements QueryTransformer {
 
  @Override
  public List<QueryFeedback> processQuery(QueryRequest request) {
    // Initialize traverser
    final CustomTraverser t = new CustomTraverser();
 
    // apply transformation to all query objects in request
    t.rewriteAll(request); 
 
    return t.feedback;
  }

To test this transformer, we inserted it into the defaultQuery workflow following the attivioLinguistics subflow.  The best location for your transformer will depend on what kind of transformation it makes.

CustomTraverser

The CustomTraverser is the first defined traverser class in the example. It simply demonstrates the form of a typical traverser.

ModifyQueryTransformer.xml
 class CustomTraverser extends QueryTraverser {
        List<QueryFeedback> feedback = null;
        @Override
        public Query rewriteQuery(Query query) {
            // Apply query transformation to node in query tree
            // Returned value will replace query in the query tree
            // Returning null will delete query from the query tree (which may result in cascading 
            // delete of parent nodes)
            // add feedback to feedback if any
            return query;
        } 
    }

Note that the CustomTraverser example (above) actually does nothing.  It returns the original query unmodified.  This is useful to use because it lets us see the unmodified query in the QueryResponse.  Using the FactBook country data, we used the DebugSearch tool to pose a Simple Query Language request for "London".  The resulting XML rendition of the query looked like this:

InPlaceModify

The InPlaceModify traverser detects a PhraseQuery  and restricts it to apply to a specific field.  This must be a field that is defined in the AIE Schema.


ModifyQueryTransformer.xml
    class InPlaceModify extends QueryTraverser {
        List<QueryFeedback> feedback = null;
        @Override
        public Query rewriteQuery(Query query) {
            if (query instanceof PhraseQuery) {
                // make in place modification
                ((PhraseQuery)query).setField("title");
            }
            return query;
        }
    }

When we run the "London" query through this traverser, the phrase query becomes restricted to the "title" field.

QueryReplace

The QueryReplace traverser replaces the original phrase query with a new one.

ModifyQueryTransformer.java
    class QueryReplace extends QueryTraverser {
        List<QueryFeedback> feedback = null;
        
        @Override
        public Query rewriteQuery(Query query) {
            if (query instanceof PhraseQuery) {
               // replace query node with new instance
               return new PhraseQuery("title", "London, England");
            }  else {
                 return query;
            }
        }
    }

In the query below, we can see that the original query was "London", and it has been replaced by a title-field query for "London, England".

 

QueryDelete

This QueryDelete traverser removes Boolean NOT queries from the request. 

ModifyQueryTransformer.java
    class QueryDelete extends QueryTraverser {
        List<QueryFeedback> feedback = null;
        
        @Override
        public Query rewriteQuery(Query query) {
            if (query instanceof BooleanNotQuery) {
                return null; // remove not queries from tree
            } else { 
                return query;
            }
        }
    }

If we use the Advanced Query Language to search for "AND(London, NOT(England))", the QueryDelete traverser removes the Boolean phrase query.

.

CustomPhraseQueryRewrite

One can append parameters to queries. These parameters are inherited by child queries.  The QueryTraverser can test for a parameter setting on a query and perform query modification based on the value.

For instance, we can add these two lines to the top of ModifyQueryTransformer to set a parameter on the incoming query.

        Query q = request.getQuery();
        q.setParameter("custom.rewrite", true);

Then we can create a QueryTraverser that tests for this parameter.  If the parameter is true, then restrict the phrase query to a specific field.

ModifyQueryTransformer.java
    //Custom query traverser that will apply the field "customField" to any phrase query annotated with "custom.rewrite" set to true
    //"custom.rewrite" parameter will be inherited from parent queries.
    public class CustomPhraseQueryRewrite extends QueryTraverser {
        List<QueryFeedback> feedback = null;
        @Override
        protected Query rewriteQuery(final Query query) {
            if ((query instanceof PhraseQuery) && getParameter("custom.rewrite", true)) {
                // set field to "customField"
                ((PhraseQuery)query).setField("title");
                return query;
            } else {
                // not a phrase query, or custom rewrite not enabled
                return query;
            }
        }
    }

Using the query "London", we can see that the custom.rewrite parameter was set as intended, and that the QueryTraverser correctly modified the query by restricting it to the title field.

 

 

 

 

 

 

  • No labels