All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.solr.client.solrj.response.QueryResponse Maven / Gradle / Ivy

There is a newer version: 9.7.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.solr.client.solrj.response;

import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.beans.DocumentObjectBinder;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;

import java.util.*;

/**
 * 
 *
 * @since solr 1.3
 */
@SuppressWarnings("unchecked")
public class QueryResponse extends SolrResponseBase 
{
  // Direct pointers to known types
  private NamedList _header = null;
  private SolrDocumentList _results = null;
  private NamedList _sortvalues = null;
  private NamedList _facetInfo = null;
  private NamedList _debugInfo = null;
  private NamedList _highlightingInfo = null;
  private NamedList> _spellInfo = null;
  private NamedList _statsInfo = null;
  private NamedList> _termsInfo = null;

  // Grouping response
  private NamedList _groupedInfo = null;
  private GroupResponse _groupResponse = null;

  // Facet stuff
  private Map _facetQuery = null;
  private List _facetFields = null;
  private List _limitingFacets = null;
  private List _facetDates = null;
  private List _facetRanges = null;
  private NamedList> _facetPivot = null;

  // Highlight Info
  private Map>> _highlighting = null;

  // SpellCheck Response
  private SpellCheckResponse _spellResponse = null;

  // Terms Response
  private TermsResponse _termsResponse = null;
  
  // Field stats Response
  private Map _fieldStatsInfo = null;
  
  // Debug Info
  private Map _debugMap = null;
  private Map _explainMap = null;

  // utility variable used for automatic binding -- it should not be serialized
  private transient final SolrServer solrServer;
  
  public QueryResponse(){
    solrServer = null;
  }
  
  /**
   * Utility constructor to set the solrServer and namedList
   */
  public QueryResponse( NamedList res , SolrServer solrServer){
    this.setResponse( res );
    this.solrServer = solrServer;
  }

  @Override
  public void setResponse( NamedList res )
  {
    super.setResponse( res );
    
    // Look for known things
    for( int i=0; i) res.getVal( i );
      }
      else if( "response".equals( n ) ) {
        _results = (SolrDocumentList) res.getVal( i );
      }
      else if( "sort_values".equals( n ) ) {
        _sortvalues = (NamedList) res.getVal( i );
      }
      else if( "facet_counts".equals( n ) ) {
        _facetInfo = (NamedList) res.getVal( i );
        // extractFacetInfo inspects _results, so defer calling it
        // in case it hasn't been populated yet.
      }
      else if( "debug".equals( n ) ) {
        _debugInfo = (NamedList) res.getVal( i );
        extractDebugInfo( _debugInfo );
      }
      else if( "grouped".equals( n ) ) {
        _groupedInfo = (NamedList) res.getVal( i );
        extractGroupedInfo( _groupedInfo );
      }
       else if( "highlighting".equals( n ) ) {
        _highlightingInfo = (NamedList) res.getVal( i );
        extractHighlightingInfo( _highlightingInfo );
      }
      else if ( "spellcheck".equals( n ) )  {
        _spellInfo = (NamedList>) res.getVal( i );
        extractSpellCheckInfo( _spellInfo );
      }
      else if ( "stats".equals( n ) )  {
        _statsInfo = (NamedList) res.getVal( i );
        extractStatsInfo( _statsInfo );
      }
      else if ( "terms".equals( n ) ) {
        _termsInfo = (NamedList>) res.getVal( i );
        extractTermsInfo( _termsInfo );
      }
    }
    if(_facetInfo != null) extractFacetInfo( _facetInfo );
  }

  private void extractSpellCheckInfo(NamedList> spellInfo) {
    _spellResponse = new SpellCheckResponse(spellInfo);
  }

  private void extractTermsInfo(NamedList> termsInfo) {
    _termsResponse = new TermsResponse(termsInfo);
  }
  
  private void extractStatsInfo(NamedList info) {
    if( info != null ) {
      _fieldStatsInfo = new HashMap();
      NamedList> ff = (NamedList>) info.get( "stats_fields" );
      if( ff != null ) {
        for( Map.Entry> entry : ff ) {
          NamedList v = entry.getValue();
          if( v != null ) {
            _fieldStatsInfo.put( entry.getKey(), 
                new FieldStatsInfo( v, entry.getKey() ) );
          }
        }
      }
    }
  }

  private void extractDebugInfo( NamedList debug )
  {
    _debugMap = new LinkedHashMap(); // keep the order
    for( Map.Entry info : debug ) {
      _debugMap.put( info.getKey(), info.getValue() );
    }

    // Parse out interesting bits from the debug info
    _explainMap = new HashMap();
    NamedList explain = (NamedList)_debugMap.get( "explain" );
    if( explain != null ) {
      for( Map.Entry info : explain ) {
        String key = info.getKey();
        _explainMap.put( key, info.getValue() );
      }
    }
  }

  private void extractGroupedInfo( NamedList info ) {
    if ( info != null ) {
      _groupResponse = new GroupResponse();
      int size = info.size();
      for (int i=0; i < size; i++) {
        String fieldName = info.getName(i);
        Object fieldGroups =  info.getVal(i);
        SimpleOrderedMap simpleOrderedMap = (SimpleOrderedMap) fieldGroups;

        Object oMatches = simpleOrderedMap.get("matches");
        Object oNGroups = simpleOrderedMap.get("ngroups");
        Object oGroups = simpleOrderedMap.get("groups");
        Object queryCommand = simpleOrderedMap.get("doclist");
        if (oMatches == null) {
          continue;
        }

        if (oGroups != null) {
          Integer iMatches = (Integer) oMatches;
          ArrayList groupsArr = (ArrayList) oGroups;
          GroupCommand groupedCommand;
          if (oNGroups != null) {
            Integer iNGroups = (Integer) oNGroups;
            groupedCommand = new GroupCommand(fieldName, iMatches, iNGroups);
          } else {
            groupedCommand = new GroupCommand(fieldName, iMatches);
          }

          for (Object oGrp : groupsArr) {
            SimpleOrderedMap grpMap = (SimpleOrderedMap) oGrp;
            Object sGroupValue = grpMap.get( "groupValue");
            SolrDocumentList doclist = (SolrDocumentList) grpMap.get( "doclist");
            Group group = new Group(sGroupValue != null ? sGroupValue.toString() : null, doclist) ;
            groupedCommand.add(group);
          }

          _groupResponse.add(groupedCommand);
        } else if (queryCommand != null) {
          Integer iMatches = (Integer) oMatches;
          GroupCommand groupCommand = new GroupCommand(fieldName, iMatches);
          SolrDocumentList docList = (SolrDocumentList) queryCommand;
          groupCommand.add(new Group(fieldName, docList));
          _groupResponse.add(groupCommand);
        }
      }
    }
  }

  private void extractHighlightingInfo( NamedList info )
  {
    _highlighting = new HashMap>>();
    for( Map.Entry doc : info ) {
      Map> fieldMap = new HashMap>();
      _highlighting.put( doc.getKey(), fieldMap );
      
      NamedList> fnl = (NamedList>)doc.getValue();
      for( Map.Entry> field : fnl ) {
        fieldMap.put( field.getKey(), field.getValue() );
      }
    }
  }

  private void extractFacetInfo( NamedList info )
  {
    // Parse the queries
    _facetQuery = new LinkedHashMap();
    NamedList fq = (NamedList) info.get( "facet_queries" );
    if (fq != null) {
      for( Map.Entry entry : fq ) {
        _facetQuery.put( entry.getKey(), entry.getValue() );
      }
    }
    
    // Parse the facet info into fields
    // TODO?? The list could be  or ?  If always  then we can switch to 
    NamedList> ff = (NamedList>) info.get( "facet_fields" );
    if( ff != null ) {
      _facetFields = new ArrayList( ff.size() );
      _limitingFacets = new ArrayList( ff.size() );
      
      long minsize = _results == null ? Long.MAX_VALUE :_results.getNumFound();
      for( Map.Entry> facet : ff ) {
        FacetField f = new FacetField( facet.getKey() );
        for( Map.Entry entry : facet.getValue() ) {
          f.add( entry.getKey(), entry.getValue().longValue() );
        }
        
        _facetFields.add( f );
        FacetField nl = f.getLimitingFields( minsize );
        if( nl.getValueCount() > 0 ) {
          _limitingFacets.add( nl );
        }
      }
    }
    
    //Parse date facets
    NamedList> df = (NamedList>) info.get("facet_dates");
    if (df != null) {
      // System.out.println(df);
      _facetDates = new ArrayList( df.size() );
      for (Map.Entry> facet : df) {
        // System.out.println("Key: " + facet.getKey() + " Value: " + facet.getValue());
        NamedList values = facet.getValue();
        String gap = (String) values.get("gap");
        Date end = (Date) values.get("end");
        FacetField f = new FacetField(facet.getKey(), gap, end);
        
        for (Map.Entry entry : values)   {
          try {
            f.add(entry.getKey(), Long.parseLong(entry.getValue().toString()));
          } catch (NumberFormatException e) {
            //Ignore for non-number responses which are already handled above
          }
        }
        
        _facetDates.add(f);
      }
    }

    //Parse range facets
    NamedList> rf = (NamedList>) info.get("facet_ranges");
    if (rf != null) {
      _facetRanges = new ArrayList( rf.size() );
      for (Map.Entry> facet : rf) {
        NamedList values = facet.getValue();
        Object rawGap = values.get("gap");

        RangeFacet rangeFacet;
        if (rawGap instanceof Number) {
          Number gap = (Number) rawGap;
          Number start = (Number) values.get("start");
          Number end = (Number) values.get("end");

          Number before = (Number) values.get("before");
          Number after = (Number) values.get("after");
          Number between = (Number) values.get("between");

          rangeFacet = new RangeFacet.Numeric(facet.getKey(), start, end, gap, before, after, between);
        } else {
          String gap = (String) rawGap;
          Date start = (Date) values.get("start");
          Date end = (Date) values.get("end");

          Number before = (Number) values.get("before");
          Number after = (Number) values.get("after");
          Number between = (Number) values.get("between");

          rangeFacet = new RangeFacet.Date(facet.getKey(), start, end, gap, before, after, between);
        }

        NamedList counts = (NamedList) values.get("counts");
        for (Map.Entry entry : counts)   {
          rangeFacet.addCount(entry.getKey(), entry.getValue());
        }

        _facetRanges.add(rangeFacet);
      }
    }
    
    //Parse pivot facets
    NamedList pf = (NamedList) info.get("facet_pivot");
    if (pf != null) {
      _facetPivot = new NamedList>();
      for( int i=0; i)pf.getVal(i) ) );
      }
    }
  }
  
  protected List readPivots( List list )
  {
    ArrayList values = new ArrayList( list.size() );
    for( NamedList nl : list ) {
      // NOTE, this is cheating, but we know the order they are written in, so no need to check
      String f = (String)nl.getVal( 0 );
      Object v = nl.getVal( 1 );
      int cnt = ((Integer)nl.getVal( 2 )).intValue();
      List p = (nl.size()<4)?null:readPivots((List)nl.getVal(3) );
      values.add( new PivotField( f, v, cnt, p ) );
    }
    return values;
  }

  //------------------------------------------------------
  //------------------------------------------------------

  /**
   * Remove the field facet info
   */
  public void removeFacets() {
    _facetFields = new ArrayList();
  }
  
  //------------------------------------------------------
  //------------------------------------------------------

  public NamedList getHeader() {
    return _header;
  }

  public SolrDocumentList getResults() {
    return _results;
  }
 
  public NamedList getSortValues(){
    return _sortvalues;
  }

  public Map getDebugMap() {
    return _debugMap;
  }

  public Map getExplainMap() {
    return _explainMap;
  }

  public Map getFacetQuery() {
    return _facetQuery;
  }

  /**
   * Returns the {@link GroupResponse} containing the group commands.
   * A group command can be the result of one of the following parameters:
   * 
    *
  • group.field *
  • group.func *
  • group.query *
* * @return the {@link GroupResponse} containing the group commands */ public GroupResponse getGroupResponse() { return _groupResponse; } public Map>> getHighlighting() { return _highlighting; } public SpellCheckResponse getSpellCheckResponse() { return _spellResponse; } public TermsResponse getTermsResponse() { return _termsResponse; } /** * See also: {@link #getLimitingFacets()} */ public List getFacetFields() { return _facetFields; } public List getFacetDates() { return _facetDates; } public List getFacetRanges() { return _facetRanges; } public NamedList> getFacetPivot() { return _facetPivot; } /** get * * @param name the name of the * @return the FacetField by name or null if it does not exist */ public FacetField getFacetField(String name) { if (_facetFields==null) return null; for (FacetField f : _facetFields) { if (f.getName().equals(name)) return f; } return null; } public FacetField getFacetDate(String name) { if (_facetDates == null) return null; for (FacetField f : _facetDates) if (f.getName().equals(name)) return f; return null; } /** * @return a list of FacetFields where the count is less then * then #getResults() {@link SolrDocumentList#getNumFound()} * * If you want all results exactly as returned by solr, use: * {@link #getFacetFields()} */ public List getLimitingFacets() { return _limitingFacets; } public List getBeans(Class type){ return solrServer == null ? new DocumentObjectBinder().getBeans(type,_results): solrServer.getBinder().getBeans(type, _results); } public Map getFieldStatsInfo() { return _fieldStatsInfo; } }