rainyzz's blog

使用Solr的Facet实现统计

最近在做一个项目,项目要求要对数据库中的数据进行各种GROUP BY,但是由于项目数据库中有很多的JOIN操作,直接执行SQL语句很慢,我就在想能不能用Facet模拟一下GROUP BY操作,并且将JOIN操作都放在数据导入的时候,然后建好索引后再统计就会快很多。

###Facet介绍
Facet算Solr一个比较重要的特性,中文应该叫做分片搜索,常见的应用场景就是比如我在淘宝上搜索“移动硬盘”,然后会出来很多的统计字段,如图包括了硬盘的品牌,缓存容量,转速等。Facet主要功能就是统计搜索结果中如品牌字段,结果中的所有数据里这个字段的取值都有哪些和相应的数量,如希捷有多少个,三星有多少个,方便用户进行进一步的筛选。

从这里可以看出来Facet达到的效果其实和GROUP BY是一样的,同时Facet也支持多级的嵌套,相当于多个GROUP BY操作。

###分析功能实现

举例一个最基本的查询语句为

1
2
http://localhost:8983/solr/order/select?q=*%3A*&&stats=true&facet=true
&stats.field={!tag=piv1}id&facet.pivot={!stats=piv1}A000,A001

其中,前半部分为Solr服务器的地址,select后面是相关的查询语句,首先将stat和facet功能开启,然后选择stats功能针对的字段是id,facet功能针对的字段是A000与A001,然后stats与facet通过piv1这个字段联系起来,即对A000与A001字段做统计。一个示意的统计结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"facet_pivot":{
"A000,A001":[{
"field":"A000",
"value":"A",
"count":54061,
"pivot":[{
"field":"A001",
"value":"5884559",
"count":216,
"stats":{
"stats_fields":{
"id":{
"min":"100048",
"max":"99607",
"count":216,
"missing":0}}}},

结果中首先显示了A000字段取值为”A”的问的数量总共有54061条,然后在A000字段取值为”A”的条件下,A001字段取值为“5884559”的共有216条,其中对id进行stats统计,显示其中的最小值,最大值,由于这个例子中的id不是数值型字段,最大最小值可能不太准确。

在实际系统实现中,查询语句和参数可能还会再要复杂一些,但原理与上述并无太大区别。在接受用户选择的统计字段统计量后,系统使用Solr进行查询,将结果存储到相关的数据结构中,然后将结果进行可视化。