solrj 开发solr查询统计方法

java、solrj API开发solr查询统计方法

solr常用的查询统计,通过solrj API实现, 有一般的条件过滤查询、分组查询、聚合查询等


import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.FieldStatsInfo;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.FacetField.Count;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;

public class SolrQueryUtil {
	
	//solr服务
	static HttpSolrServer solr = getServer();
	
	//删除索引数据
	public static void del() throws Exception{
		solr.deleteByQuery("*:*", 1000);//删除全部索引数据
		solr.deleteById("myid",1000);//根据id删除单个索引(可以传入id的list,删除多个id)
		solr.commit();
	}
	
	
	//查询
	public static void query() throws Exception{
		SolrQuery query;
		QueryResponse rsp = null;
		query = new SolrQuery();
		query.set("start", "0");
		query.set("q", "*:*");
		
		//query.set("start", "0"); 
		//query.set("rows", "10");//设置每页查询条数,可用于分页处理
		
		String outputField = "";//solr的索引字段设定值
		//                    outputField 对应的索引字段
		query.addFilterQuery("sz_areacode:" + outputField);//添加查询限定条件,如果没有FilterQuery字段,即查询全部信息
		//范围查询,注意TO和空格分隔!*表示通配符,[]表示闭包括界限,{}表示开包括界限
		query.addFilterQuery("sz_age:" + "[18 "+"TO"+" *");// >=18
		query.addFilterQuery("sz_age:" + "[18 "+"TO"+" 30]");// >=18    <=30
		query.addFilterQuery("sz_age:" + "{18 "+"TO"+" 30}");// >18     <30
		//多个字段设置,表示并集,相当sql的and

		query.addFilterQuery("sz_age:" + "18" +" OR "+"sz_address:"+"福田");//表示或查询
		
		//通配查询,*表示通配所有字符      ?表示通配一个字符
		query.addFilterQuery("sz_address:" + "南山区"+"*");//南山区 后面所有通配
		query.addFilterQuery("sz_address:" + "*"+"南山区"+"*");//模糊查询,包含 南山区 的所有信息
		query.addFilterQuery("sz_address:" + "*"+"南山区");//南山区 前面所有通配
		
		query.addFilterQuery("sz_areacode:" +"4403"+"??");//4403 后面通配两个字符
		
		query.addSort("sz_age", ORDER.desc); //desc 降序       asc 升序
		
		rsp = solr.query(query);
		SolrDocumentList docs = rsp.getResults();
		long num = docs.getNumFound();//数据总条数
		
		if (docs.size() != 0) {
			for (SolrDocument doc : docs) {
				String age = doc.getFieldValue("sz_age").toString();//获取字段的字符信息
			}
		} 
		
	}
	
	//分组查询(可用于查询分组、字段去重)
	public static void queryFacet() throws Exception {
		SolrQuery query;
		QueryResponse rsp = null;
		List<FacetField> facets = null;
		query = new SolrQuery();
		query.set("start", "0");
		query.set("q", "*:*");
		
		query.setFacet(true);
		//query.setFacetMinCount(1);//设置为分组只统计分组数据大于等于1的,即分组统计count字段为0的不显示
		//query.setFacetMissing(false);//count字段为null的不统计
		//query.setFacetLimit(10);//返回的统计数量条数,默认按count降序。可用facet.sort 修改
		query.addFacetField("sz_areacode");
		//query.addFacetField("sz_repyear");//多个字段可以同时分组,相互不影响,通过facet.getName()区分
		
		rsp = solr.query(query);
		facets = rsp.getFacetFields();
		
		for (FacetField facet : facets) {
			//System.out.println(facet.getName());//区分不同字段的分组
			List<Count> counts = facet.getValues();//获取分组后的统计信息
			System.out.println(counts);
			int fileds = counts.size();//分组的数量
			for (Count count : counts) {
				long num = count.getCount();//每一个分组所包含的条数,跟getName对应
				String name = count.getName();//每一个分组的名称
			}
		}
		
	}
	
	//聚合查询(可用查询字段数值总和,注意只有数据类型的字段,才能使用)
	public static void queryFields() throws Exception {
		SolrQuery query;
		QueryResponse rsp = null;
		FieldStatsInfo fieldStatsInfo = null;
		Map<String,FieldStatsInfo> fieldMap = null;
		query = new SolrQuery();
		query.set("start", "0");
		query.set("q", "*:*");
		
		query.setGetFieldStatistics(true);
		query.setGetFieldStatistics("sz_areacode");//设置要聚合查询的字段,可以同时设置多个,相互不影响
		//query.setGetFieldStatistics("sz_address");
		
		rsp = solr.query(query);
		fieldMap = rsp.getFieldStatsInfo();
		
		if (!fieldMap.isEmpty()) {
			for( String  key :fieldMap.keySet()) {
				if (key=="sz_areacode" || "sz_areacode".equals(key)) {
		            fieldStatsInfo = fieldMap.get(key);
		            long allNum = fieldStatsInfo.getCount();//查询的数据表的总条数
		            long numSum = Math.round((double)fieldStatsInfo.getSum());//聚合字段的总和
		            fieldStatsInfo.getMax();//字段最大数
		            fieldStatsInfo.getMin();//字段最小数
		            fieldStatsInfo.getStddev();//字段的平均数
		            fieldStatsInfo.getName();//聚合的字段,也可用来判断不同的聚合
				}
				else if (key=="sz_address" || "sz_address".equals(key)) {
					fieldStatsInfo = fieldMap.get(key);
					//通过判断key区分不同的聚合字段
				}
				
			}
		}
	}
	
	
	public static HttpSolrServer getServer() {			
		solr = new HttpSolrServer("http://master:8983/solr/sz_grid");
		solr.setParser(new XMLResponseParser());
		solr.setConnectionTimeout(3000);
		solr.setDefaultMaxConnectionsPerHost(100);
		solr.setMaxTotalConnections(100);
		return solr;		
	}
	
}


最后再附上网上一些关于分组查询的设置:

1、facet.prefix  
    表示Facet字段值的前缀.比如facet.field=cpu&facet.prefix=Intel,那么对cpu字段进行Facet查询,返回的cpu都是以“Intel”开头的。  
2、facet.sort  
    表示Facet字段值以哪种顺序返回.可接受的值为true(count)|false(index,lex). true(count)表示按照count降序; false(index,lex)表示按照字段值升序(字母,数字的顺序)排列.默认情况下为true(count).当facet.limit值为负数时,默认facet.sort= false(index,lex).  
3、facet.limit  
    限制Facet字段返回的结果条数.默认值为100.如果此值为负数,表示不限制.  
4、facet.offset  
    返回结果集的偏移量,默认为0.它与facet.limit配合使用可以达到分页的效果.  
5、facet.mincount  
    限制了Facet字段值的最小count,默认为0.合理设置该参数可以将用户的关注点集中在少数比较热门的领域.相当于group by having  
6、facet.missing  
    默认为””,如果设置为true或者on,那么将统计那些该Facet字段值为null的记录.  
7、facet.method  
    取值为enum或fc,默认为fc.该字段表示了两种Facet的算法,与执行效率相关.  
    enum适用于字段值比较少的情况,比如字段类型为布尔型,或者字段表示中国的所有省份.Solr会遍历该字段的所有取值,并从filterCache里为每个值分配一个filter(这里要求solrconfig.xml里对filterCache的设置足够大).然后计算每个filter与主查询的交集.  
    fc(表示Field Cache)适用于字段取值比较多,但在每个文档里出现次数比较少的情况.Solr会遍历所有的文档,在每个文档内搜索Cache内的值,如果找到就将Cache内该值的count加1.  
8、facet.enum.cache.minDf  
    当facet.method=enum时,此参数其作用,minDf表示minimum document frequency.也就是文档内出现某个关键字的最少次数.该参数默认值为0.设置该参数可以减少filterCache的内存消耗,但会增加总的查询时间(计算交集的时间增加了).如果设置该值的话,官方文档建议优先尝试25-50内的值. 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章