solr的facet解读

开发采用更加灵活的solr搜索服务器来实现分层功能。

1.QueryResponse类:

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
public class QueryResponse extends SolrResponseBase   
{  
  // Direct pointers to known types  
  private NamedList<Object> _header = null;  
  private SolrDocumentList _results = null;  
  private NamedList<ArrayList> _sortvalues = null;  
  private NamedList<Object> _facetInfo = null;  
  private NamedList<Object> _debugInfo = null;  
  private NamedList<Object> _highlightingInfo = null;  
  private NamedList<Object> _spellInfo = null;  
 
  // Facet stuff  
  private Map<String,Integer> _facetQuery = null;  
  private List<FacetField> _facetFields = null;  
  private List<FacetField> _limitingFacets = null;  
  private List<FacetField> _facetDates = null;  
 
  // Highlight Info  
  private Map<String,Map<String,List<String>>> _highlighting = null;  
 
  // SpellCheck Response  
  private SpellCheckResponse _spellResponse = null;  
    
  // Debug Info  
  private Map<String,Object> _debugMap = null;  
  private Map<String,String> _explainMap = null;  
 
  // utility variable used for automatic binding -- it should not be serialized  
  private transient final SolrServer solrServer;  
//.....  
//.....  
private void extractFacetInfo( NamedList<Object> info )  
  {  
    // Parse the queries  
    _facetQuery = new HashMap<String, Integer>();  
    NamedList<Integer> fq = (NamedList<Integer>) info.get( "facet_queries" );  
    for( Map.Entry<String, Integer> entry : fq ) {  
      _facetQuery.put( entry.getKey(), entry.getValue() );  
    }  
      
    // Parse the facet info into fields  
    // TODO?? The list could be <int> or <long>?  If always <long> then we can switch to <Long>  
    NamedList<NamedList<Number>> ff = (NamedList<NamedList<Number>>) info.get( "facet_fields" );  
    if( ff != null ) {  
      _facetFields = new ArrayList<FacetField>( ff.size() );  
      _limitingFacets = new ArrayList<FacetField>( ff.size() );  
        
      long minsize = _results.getNumFound();  
      for( Map.Entry<String,NamedList<Number>> facet : ff ) {  
        FacetField f = new FacetField( facet.getKey() );  
        for( Map.Entry<String, Number> 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<NamedList<Object>> df = (NamedList<NamedList<Object>>) info.get("facet_dates");  
    if (df != null) {  
      // System.out.println(df);  
      _facetDates = new ArrayList<FacetField>( df.size() );  
      for (Map.Entry<String, NamedList<Object>> facet : df) {  
        // System.out.println("Key: " + facet.getKey() + " Value: " + facet.getValue());  
        NamedList<Object> 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<String, Object> 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);  
      }  
    }  
  }  

public class QueryResponse extends SolrResponseBase
{
  // Direct pointers to known types
  private NamedList<Object> _header = null;
  private SolrDocumentList _results = null;
  private NamedList<ArrayList> _sortvalues = null;
  private NamedList<Object> _facetInfo = null;
  private NamedList<Object> _debugInfo = null;
  private NamedList<Object> _highlightingInfo = null;
  private NamedList<Object> _spellInfo = null;

  // Facet stuff
  private Map<String,Integer> _facetQuery = null;
  private List<FacetField> _facetFields = null;
  private List<FacetField> _limitingFacets = null;
  private List<FacetField> _facetDates = null;

  // Highlight Info
  private Map<String,Map<String,List<String>>> _highlighting = null;

  // SpellCheck Response
  private SpellCheckResponse _spellResponse = null;
 
  // Debug Info
  private Map<String,Object> _debugMap = null;
  private Map<String,String> _explainMap = null;

  // utility variable used for automatic binding -- it should not be serialized
  private transient final SolrServer solrServer;
//.....
//.....
private void extractFacetInfo( NamedList<Object> info )
  {
    // Parse the queries
    _facetQuery = new HashMap<String, Integer>();
    NamedList<Integer> fq = (NamedList<Integer>) info.get( "facet_queries" );
    for( Map.Entry<String, Integer> entry : fq ) {
      _facetQuery.put( entry.getKey(), entry.getValue() );
    }
   
    // Parse the facet info into fields
    // TODO?? The list could be <int> or <long>?  If always <long> then we can switch to <Long>
    NamedList<NamedList<Number>> ff = (NamedList<NamedList<Number>>) info.get( "facet_fields" );
    if( ff != null ) {
      _facetFields = new ArrayList<FacetField>( ff.size() );
      _limitingFacets = new ArrayList<FacetField>( ff.size() );
     
      long minsize = _results.getNumFound();
      for( Map.Entry<String,NamedList<Number>> facet : ff ) {
        FacetField f = new FacetField( facet.getKey() );
        for( Map.Entry<String, Number> 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<NamedList<Object>> df = (NamedList<NamedList<Object>>) info.get("facet_dates");
    if (df != null) {
      // System.out.println(df);
      _facetDates = new ArrayList<FacetField>( df.size() );
      for (Map.Entry<String, NamedList<Object>> facet : df) {
        // System.out.println("Key: " + facet.getKey() + " Value: " + facet.getValue());
        NamedList<Object> 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<String, Object> 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);
      }
    }
  }
}

_facetFields:所有的分层结果  使用 getFacetField(String name) 获得结果

_limitingFacets:facetFields中个数大于0的分层,使用getLimitingFacets()返回所有Count个数大于0的FacetField。

_facetDates:根据日期的分层结果 getFacetDate(String name)

例外,要使用Facet功能,除了设置 Field外,还需要将facet属性设置为true,默认是false的。

view plaincopy to clipboardprint?
params.set("facet", "true");  
params.set("facet.field", "site_search");  
params.set("facet.field", "kindtag_search");


 

1. FacetField 内嵌了 Count类,Count类保存了被分层出来的的 词 以及该词在搜有搜索出来的文档中出现的次数。


view plaincopy to clipboardprint?
package org.apache.solr.client.solrj.response;  
 
import java.io.Serializable;  
import java.util.ArrayList;  
import java.util.Date;  
import java.util.List;  
 
import org.apache.solr.client.solrj.util.ClientUtils;  
   
 /** 
  * A utility class to hold the facet response.  It could use the NamedList container, 
  * but for JSTL, it is nice to have something that implements List so it can be iterated 
  *  
  * @version $Id: FacetField.java 638357 2008-03-18 13:12:27Z gsingers $ 
  * @since solr 1.3 
  */ 
 public class FacetField implements Serializable  
 {  
   public static class Count implements Serializable   
   {  
     private String _name = null;  
     private long _count = 0;  
     // hang onto the FacetField for breadcrumb creation convenience  
     private FacetField _ff = null;  
       
     public Count( FacetField ff, String n, long c )  
     {  
       _name = n;  
       _count = c;  
       _ff = ff;  
     }  
       
     public String getName() {  
       return _name;  
     }  
       
     public void setName( String n )  
     {  
       _name = n;  
     }  
 
     public long getCount() {  
       return _count;  
     }  
       
     public void setCount( long c )  
     {  
       _count = c;  
     }  
       
     public FacetField getFacetField() {  
       return _ff;  
     }  
       
     @Override 
     public String toString()  
     {  
       return _name+" ("+_count+")";  
     }  
       
     public String getAsFilterQuery() {  
       if (_ff.getName().equals("facet_queries")) {  
         return _name;  
       }  
       return   
          ClientUtils.escapeQueryChars( _ff._name ) + ":" +   
          ClientUtils.escapeQueryChars( _name );  
     }  
   }  
     
   private String      _name   = null;  
   private List<Count> _values = null;  
   private String _gap = null;  
   private Date _end = null;  
 
//.........  
//.........方法  
 
   } 
package org.apache.solr.client.solrj.response;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.solr.client.solrj.util.ClientUtils;
 
 /**
  * A utility class to hold the facet response.  It could use the NamedList container,
  * but for JSTL, it is nice to have something that implements List so it can be iterated
  *
  * @version $Id: FacetField.java 638357 2008-03-18 13:12:27Z gsingers $
  * @since solr 1.3
  */
 public class FacetField implements Serializable
 {
   public static class Count implements Serializable
   {
     private String _name = null;
     private long _count = 0;
     // hang onto the FacetField for breadcrumb creation convenience
     private FacetField _ff = null;
    
     public Count( FacetField ff, String n, long c )
     {
       _name = n;
       _count = c;
       _ff = ff;
     }
    
     public String getName() {
       return _name;
     }
    
     public void setName( String n )
     {
       _name = n;
     }

     public long getCount() {
       return _count;
     }
    
     public void setCount( long c )
     {
       _count = c;
     }
    
     public FacetField getFacetField() {
       return _ff;
     }
    
     @Override
     public String toString()
     {
       return _name+" ("+_count+")";
     }
    
     public String getAsFilterQuery() {
       if (_ff.getName().equals("facet_queries")) {
         return _name;
       }
       return
          ClientUtils.escapeQueryChars( _ff._name ) + ":" +
          ClientUtils.escapeQueryChars( _name );
     }
   }
  
   private String      _name   = null;
   private List<Count> _values = null;
   private String _gap = null;
   private Date _end = null;

//.........
//.........方法

   }
 

一个FacetField实例拥有多个Count实例。

 

 

posted @ 2009-09-28 11:09  searchDM  阅读(1605)  评论(0编辑  收藏  举报