聚合统计 #

一、Facet(分面) #

1.1 Facet概述 #

Facet用于对搜索结果进行分组统计,常用于:

  • 分类导航
  • 品牌筛选
  • 价格区间
  • 属性筛选

1.2 字段Facet #

bash
# 基本Facet
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.field=category"

响应示例

json
{
  "facet_counts": {
    "facet_fields": {
      "category": [
        "tech", 50,
        "book", 30,
        "news", 20
      ]
    }
  }
}

1.3 Facet参数 #

参数 说明
facet 是否开启Facet
facet.field Facet字段
facet.limit 返回数量
facet.sort 排序方式
facet.mincount 最小数量
facet.missing 是否包含空值
facet.prefix 前缀过滤
facet.contains 包含过滤

1.4 多字段Facet #

bash
# 多字段Facet
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.field=category" \
  -d "facet.field=brand" \
  -d "facet.field=author"

1.5 Facet排序 #

bash
# 按数量排序(默认)
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.field=category" \
  -d "facet.sort=count"

# 按字母排序
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.field=category" \
  -d "facet.sort=index"

1.6 Facet限制 #

bash
# 限制返回数量
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.field=category" \
  -d "facet.limit=10"

# 设置最小数量
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.field=category" \
  -d "facet.mincount=5"

二、Range Facet #

2.1 数值范围 #

bash
# 价格范围Facet
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.range=price" \
  -d "facet.range.start=0" \
  -d "facet.range.end=1000" \
  -d "facet.range.gap=100"

响应示例

json
{
  "facet_counts": {
    "facet_ranges": {
      "price": {
        "counts": [
          "0.0", 10,
          "100.0", 25,
          "200.0", 30,
          "300.0", 20
        ]
      }
    }
  }
}

2.2 日期范围 #

bash
# 日期范围Facet
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.range=publish_date" \
  -d "facet.range.start=NOW-1YEAR" \
  -d "facet.range.end=NOW" \
  -d "facet.range.gap=%2B1MONTH"

2.3 Range参数 #

参数 说明
facet.range 范围字段
facet.range.start 起始值
facet.range.end 结束值
facet.range.gap 间隔
facet.range.hardend 是否硬结束
facet.range.other 其他统计

三、Query Facet #

3.1 查询Facet #

bash
# 自定义查询Facet
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.query=price:[0 TO 100]" \
  -d "facet.query=price:[100 TO 500]" \
  -d "facet.query=price:[500 TO *]"

3.2 响应示例 #

json
{
  "facet_counts": {
    "facet_queries": {
      "price:[0 TO 100]": 50,
      "price:[100 TO 500]": 30,
      "price:[500 TO *]": 20
    }
  }
}

四、Pivot Facet #

4.1 基本Pivot #

bash
# 多维度Facet
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.pivot=category,brand"

4.2 响应示例 #

json
{
  "facet_counts": {
    "facet_pivot": {
      "category,brand": [
        {
          "field": "category",
          "value": "tech",
          "count": 50,
          "pivot": [
            {
              "field": "brand",
              "value": "Apple",
              "count": 20
            },
            {
              "field": "brand",
              "value": "Samsung",
              "count": 15
            }
          ]
        }
      ]
    }
  }
}

4.3 多层Pivot #

bash
# 三层Pivot
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.pivot=category,brand,price"

五、Stats(统计) #

5.1 基本统计 #

bash
# 统计字段
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "stats=true" \
  -d "stats.field=price"

5.2 响应示例 #

json
{
  "stats": {
    "stats_fields": {
      "price": {
        "min": 10.0,
        "max": 999.0,
        "count": 100,
        "missing": 5,
        "sum": 25000.0,
        "sumOfSquares": 1000000.0,
        "mean": 250.0,
        "stddev": 150.0
      }
    }
  }
}

5.3 统计指标 #

指标 说明
min 最小值
max 最大值
count 数量
missing 空值数量
sum 总和
sumOfSquares 平方和
mean 平均值
stddev 标准差
median 中位数

5.4 分组统计 #

bash
# 按分类统计
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "stats=true" \
  -d "stats.field=price" \
  -d "stats.facet=category"

六、Grouping(分组) #

6.1 基本分组 #

bash
# 按字段分组
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "group=true" \
  -d "group.field=category" \
  -d "group.limit=5"

6.2 响应示例 #

json
{
  "grouped": {
    "category": {
      "matches": 100,
      "groups": [
        {
          "groupValue": "tech",
          "doclist": {
            "numFound": 50,
            "docs": [...]
          }
        }
      ]
    }
  }
}

6.3 分组参数 #

参数 说明
group 是否分组
group.field 分组字段
group.limit 每组数量
group.sort 组内排序
group.ngroups 返回组数
group.truncate 是否截断

6.4 查询分组 #

bash
# 按查询分组
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "group=true" \
  -d "group.query=price:[0 TO 100]" \
  -d "group.query=price:[100 TO *]"

七、JSON Facet API #

7.1 基本语法 #

bash
# JSON Facet
curl -X POST "http://localhost:8983/solr/mycore/select" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "*:*",
    "facet": {
      "categories": {
        "type": "terms",
        "field": "category"
      }
    }
  }'

7.2 Terms Facet #

bash
curl -X POST "http://localhost:8983/solr/mycore/select" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "*:*",
    "facet": {
      "categories": {
        "type": "terms",
        "field": "category",
        "limit": 10,
        "sort": {"count": "desc"}
      }
    }
  }'

7.3 Range Facet #

bash
curl -X POST "http://localhost:8983/solr/mycore/select" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "*:*",
    "facet": {
      "price_ranges": {
        "type": "range",
        "field": "price",
        "start": 0,
        "end": 1000,
        "gap": 100
      }
    }
  }'

7.4 嵌套Facet #

bash
curl -X POST "http://localhost:8983/solr/mycore/select" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "*:*",
    "facet": {
      "categories": {
        "type": "terms",
        "field": "category",
        "facet": {
          "brands": {
            "type": "terms",
            "field": "brand"
          },
          "avg_price": "avg(price)"
        }
      }
    }
  }'

7.5 聚合函数 #

函数 说明
sum(field) 求和
avg(field) 平均值
min(field) 最小值
max(field) 最大值
count() 计数
unique(field) 唯一值数量

八、实战示例 #

8.1 电商商品统计 #

bash
curl "http://localhost:8983/solr/products/select" \
  -d "q=手机" \
  -d "facet=true" \
  -d "facet.field=brand" \
  -d "facet.field=category" \
  -d "facet.range=price" \
  -d "facet.range.start=0" \
  -d "facet.range.end=10000" \
  -d "facet.range.gap=1000" \
  -d "stats=true" \
  -d "stats.field=price" \
  -d "stats.field=sales"

8.2 文章分类统计 #

bash
curl "http://localhost:8983/solr/articles/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.pivot=category,author" \
  -d "stats=true" \
  -d "stats.field=views" \
  -d "stats.facet=category"

8.3 日志分析统计 #

bash
curl "http://localhost:8983/solr/logs/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.field=level" \
  -d "facet.field=host" \
  -d "facet.range=timestamp" \
  -d "facet.range.start=NOW-1DAY" \
  -d "facet.range.end=NOW" \
  -d "facet.range.gap=%2B1HOUR"

8.4 使用JSON Facet #

bash
curl -X POST "http://localhost:8983/solr/products/select" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "category:手机",
    "facet": {
      "brands": {
        "type": "terms",
        "field": "brand",
        "limit": 10,
        "facet": {
          "avg_price": "avg(price)",
          "total_sales": "sum(sales)"
        }
      },
      "price_stats": {
        "type": "range",
        "field": "price",
        "start": 0,
        "end": 10000,
        "gap": 1000
      }
    }
  }'

九、性能优化 #

9.1 使用DocValues #

xml
<field name="category" type="string" indexed="true" stored="true" docValues="true"/>

9.2 限制Facet数量 #

bash
# 限制返回数量
curl "http://localhost:8983/solr/mycore/select" \
  -d "q=*:*" \
  -d "facet=true" \
  -d "facet.field=category" \
  -d "facet.limit=10"

9.3 使用缓存 #

xml
<requestHandler name="/select" class="solr.SearchHandler">
  <lst name="defaults">
    <bool name="facet">true</bool>
    <int name="facet.limit">10</int>
  </lst>
</requestHandler>

十、总结 #

聚合统计对比:

功能 说明 适用场景
Facet 分面统计 分类导航
Range Facet 范围统计 价格区间
Pivot Facet 多维统计 组合筛选
Stats 数值统计 统计分析
Grouping 分组查询 结果去重
JSON Facet 灵活聚合 复杂统计

最佳实践:

  • 使用DocValues优化性能
  • 合理限制返回数量
  • 使用JSON Facet进行复杂统计
  • 缓存常用Facet结果

下一步,让我们学习高亮与建议!

最后更新:2026-03-27