Solr-搜索引擎-入门到精通

以下是对 Apache Solr 的简介及其常用语法的快速入门指南:


一、Solr 是什么?

核心定位 :Apache Solr 是一个基于 Lucene 的高性能、开源的搜索平台,支持全文检索、分词、高亮、聚合统计等功能。

核心功能

全文搜索 :快速检索海量文本数据。

数据聚合 (Facet):统计字段分布、范围、词频等。

分布式架构 :支持水平扩展,处理 PB 级数据。

实时索引 :支持近实时(NRT)数据更新。

适用场景:电商搜索、日志分析、大数据检索、推荐系统等。


二、快速安装与启动

1. 下载与启动
复制代码
# 下载 Solr(以 9.x 为例)
wget https://dlcdn.apache.org/solr/solr/9.5.0/solr-9.5.0.tgz
tar -xzf solr-9.5.0.tgz
cd solr-9.5.0

# 启动 Solr(单机模式)
bin/solr start
2. 创建核心(Core)
复制代码
bin/solr create -c my_core

三、常用语法示例

1. 基础查询( q

• 搜索所有文档:

复制代码
q=*:*

• 指定字段搜索:

复制代码
q=title:"智能手机"

• 多条件组合(布尔逻辑):

复制代码
q=title:apple AND (category:phone OR price:[1000 TO 2000])
2. 过滤查询( fq

• 过滤特定分类:

复制代码
fq=category:electronics

• 范围过滤(价格 100-500):

复制代码
fq=price:[100 TO 500]
3. 排序( sort

• 按价格升序,评分降序:

复制代码
sort=price asc, score desc
4. 分页( start rows

• 获取第 2 页,每页 10 条:

复制代码
start=10&rows=10
5. 返回字段限制( fl

• 指定返回字段:

复制代码
fl=id,title,price

• 包含评分和计算字段:

复制代码
fl=title,price,score,sum(price,tax) as total
6. 高亮( hl

• 高亮标题和内容中的关键词:

复制代码
hl=true&hl.fl=title,content
7. 分组( group

• 按分类分组,每组返回前 3 条:

复制代码
group=true&group.field=category&group.limit=3
8. 分面统计( facet

• 统计分类分布和价格区间:

复制代码
facet=true
&facet.field=category
&facet.range=price
&facet.range.start=0
&facet.range.end=1000
&facet.range.gap=100

四、高级功能语法

1. 使用 eDisMax 解析器
复制代码
defType=edismax
&qf=title^2 content^1          # 字段加权
&bq=in_stock:true^10           # 提升库存商品
&bf=log(sales)                 # 按销量动态加权
2. 模糊搜索与通配符

• 模糊匹配(允许 1 字符差异):

复制代码
q=applle~1

• 通配符搜索:

复制代码
q=title:app*     # 匹配 "apple", "application" 等
3. 函数查询

• 按时间衰减排序:

复制代码
sort=recip(ms(NOW,create_time),1,1000,1000) desc

五、最佳实践

  1. 优先使用 fq过滤:提升性能(结果可缓存)。
  2. 限制返回字段( fl:减少网络传输开销。
  3. 避免全通配符 *:*:大数据集下性能差。
  4. 合理配置分词器:根据业务需求定制字段的分词规则。

六、总结

Solr 是一个功能强大的搜索引擎,适用于复杂查询和大规模数据场景。掌握以上语法后,可快速实现以下操作:

• 基础搜索、过滤、排序

• 聚合统计(分面、分组)

• 动态评分与高亮

• 分布式扩展与优化

通过结合 eDisMax 解析器和函数查询,能实现更灵活的搜索排序策略!

一、常用内置函数

1. 数学函数

|--------------------|----------|--------------------|-------------|
| 函数 | 说明 | 示例 | 应用场景 |
| abs(x) | 绝对值 | abs(-5) → 5 | 计算误差范围 |
| sqrt(x) | 平方根 | sqrt(16) → 4 | 数据标准化处理 |
| log(x) | 自然对数 | log(10) → 2.302 | 平滑指数(如销量加权) |
| pow(x,y) | x 的 y 次幂 | pow(2,3) → 8 | 非线性评分调整 |
| sum(x,y,...) | 求和 | sum(1,2,3) → 6 | 多字段数值相加 |
| product(x,y,...) | 乘积 | product(2,3) → 6 | 综合权重计算 |
| div(x,y) | 除法 | div(10,2) → 5 | 计算单价、比率 |

场景示例

  • 商品评分加权log(sales)*0.5 + rating*10
  • 价格区间标准化div(price, 100) 将价格转换为百元单位。

2. 字符串函数

|--------------------------|-----------|------------------------------------------|----------|
| 函数 | 说明 | 示例 | 应用场景 |
| concat(str1,str2) | 字符串拼接 | concat("Hello","World") → "HelloWorld" | 生成复合字段 |
| split(str,sep) | 按分隔符拆分字符串 | split("A,B,C", ",") → ["A","B","C"] | 多标签分类统计 |
| substr(str,start,len) | 截取子字符串 | substr("Solr",1,2) → "ol" | 提取部分编码字段 |
| strdist(str1,str2,alg) | 计算字符串相似度 | strdist("apple","app", "jw") → 0.96 | 模糊匹配度评分 |

场景示例

  • 地址模糊匹配strdist(address, "北京市海淀区", "jw")
  • 动态生成标题concat(brand, "-", model)

3. 日期函数

|--------------------|------------|--------------------------------------|----------|
| 函数 | 说明 | 示例 | 应用场景 |
| now() | 当前时间 | now() → "2024-07-30T12:00:00Z" | 实时数据过滤 |
| ms(date1, date2) | 计算两个日期的毫秒差 | ms(now(), publish_time) → 86400000 | 时间衰减排序 |
| dateMath(expr) | 日期运算 | dateMath(now()-1DAY) | 动态时间范围过滤 |

场景示例

  • 新闻时效性排序recip(ms(now(), publish_time), 3.16e-11, 1, 1)
  • 过滤最近一周数据fq=publish_date:[NOW-7DAYS TO NOW]

4. 条件与逻辑函数

|-------------------------------|----------|-------------------------------|-------------|
| 函数 | 说明 | 示例 | 应用场景 |
| if(cond, trueVal, falseVal) | 条件判断 | if(price>100, "高价", "低价") | 动态分类标记 |
| exists(field) | 判断字段是否存在 | exists(description) → 1 或 0 | 过滤缺失关键字段的文档 |
| and(x,y) / or(x,y) | 逻辑与/或 | and(in_stock, price<100) | 组合布尔条件 |

场景示例

  • 促销商品标识if(is_promotion, "促销中", "无促销")
  • 过滤无效商品fq=exists(image_url)

二、聚合函数(Faceting)

Solr 的聚合统计通过 Facet 实现,核心函数如下:

|---------------|-------------|---------------------------------------------|-----------|
| 聚合类型 | 说明 | 示例 | 应用场景 |
| count | 统计文档数 | facet.field=category | 按分类统计商品数量 |
| sum | 求和 | facet.query=sum(sales) | 计算总销售额 |
| avg | 平均值 | facet.query=avg(price) | 计算平均价格 |
| min / max | 最小值/最大值 | facet.query=min(price) | 价格区间分析 |
| unique | 唯一值计数(基数统计) | facet.query=unique(user_id) | 统计独立访问用户数 |
| range | 按范围分组统计 | facet.range=price&facet.range.start=0&... | 价格区间分布统计 |

场景示例

  • 电商数据分析

    bash

    facet=true
    &facet.field=category
    &facet.query=sum(sales)
    &facet.range=price
    &facet.range.start=0
    &facet.range.end=1000
    &facet.range.gap=100

输出结果:

    • 各分类商品数
    • 总销售额
    • 价格在 0-100、100-200 等区间的商品数量。

三、高级应用场景

1. 综合评分排序(电商搜索)
复制代码
bash


q=手机&
defType=edismax&
qf=title^2 brand^1&
bf=product(log(sales), recip(price,1,1000,1000))&
fl=title,price,sales,score
  • 效果:销量高且价格低的商品排名更靠前。
2. 时间衰减排序(新闻推荐)
复制代码
bash


q=科技&
bf=recip(ms(NOW,publish_time), 3.16e-11, 1, 1)&
fl=title,publish_time,score
  • 效果:新发布的新闻优先展示。
3. 动态价格分段统计(数据分析)
复制代码
bash


facet.range=price&
facet.range.start=0&
facet.range.end=1000&
facet.range.gap=100&
facet=on
  • 效果:统计不同价格区间的商品数量(0-100元、100-200元等)。

四、最佳实践

  1. 优先使用 fq****过滤数据:提升聚合性能。
  2. 避免复杂函数嵌套 :如 sqrt(log(div(x,y))) 可能影响性能。
  3. 合理选择聚合粒度 :范围查询(facet.range)的间隔(gap)不宜过小。
  4. 结合缓存机制:对高频聚合查询启用结果缓存。

日期查询【最近七天】:

在 Solr 中,日期范围查询的正确语法应使用 **NOW 和日期数学表达式**,而不是 date_math 函数。以下是修复后的语法及详细说明:


正确语法

复制代码
bash


create_time:[NOW-7DAYS TO NOW]

或(更严谨的格式,指定时间单位):

复制代码
bash


create_time:[NOW-7DAYS/DAY TO NOW/DAY]  # 精确到天的范围

语法说明

1. 核心规则
  • **NOW**:表示当前时间(UTC 时区)。
  • **-7DAYS**:日期数学表达式,向前推 7 天。
  • **[start TO end]**:闭区间范围(包含边界值)。
  • **/DAY**:将时间截断到天级别(可选,用于对齐日期边界)。
2. 动态时间计算

|-----------------|--------------|------------------------------------|
| 表达式 | 含义 | 示例值(假设当前为 2024-07-30 |
| NOW-7DAYS | 7 天前的当前时刻 | 2024-07-23T12:00:00Z |
| NOW-7DAYS/DAY | 7 天前的零点(UTC) | 2024-07-23T00:00:00Z |
| NOW/DAY | 当前日期的零点(UTC) | 2024-07-30T00:00:00Z |

3. URL 转义

在 HTTP 请求中需转义特殊字符(如 [, ], /):

复制代码
bash


# 实际请求示例(注意转义方括号和斜杠)
q=create_time:%5BNOW-7DAYS%20TO%20NOW%5D

完整示例

场景:查询最近 7 天内创建的数据
复制代码
bash


http://localhost:8983/solr/your-core/select?
q=*:*&
fq=create_time:[NOW-7DAYS TO NOW]&
fl=id,create_time
结果
复制代码
json


{
  "response": {
    "docs": [
      { "id": "1", "create_time": "2024-07-25T08:30:00Z" },
      { "id": "2", "create_time": "2024-07-28T15:45:00Z" }
    ]
  }
}

常见问题

1. 时区问题
  • Solr 默认使用 UTC 时区 ,若数据存储为本地时间(如 CST),需转换时区:

    bash

    create_time:[NOW-7DAYS+8HOURS TO NOW+8HOURS] # 假设数据为 UTC+8 时区

2. 字段类型

确保 create_time 字段类型为 Solr 日期类型(如 datedatePoint)。

3. 精确时间对齐

若需按天过滤(忽略时分秒),使用截断语法:

复制代码
bash


create_time:[NOW-7DAYS/DAY TO NOW/DAY]

等价于:

复制代码
bash


create_time:[2024-07-23T00:00:00Z TO 2024-07-30T00:00:00Z]

进阶用法

动态时间范围

结合参数化请求(如 $__time 占位符):

复制代码
bash


create_time:[$__time-7DAYS TO $__time]

通过此语法,你可以精准筛选出指定时间范围内的文档,避免语法错误!

bq bf q^的区别

在 Solr 中,bq(Boost Query)、bf(Boost Function)和 q 中的 ^ 字段加权都能影响文档评分,但它们的机制和应用场景有本质区别。以下是详细对比和场景指南:


一、核心区别

|-----------|-------------------------------------------------|--------------------------|--------------------------|
| 功能 | ** q 字段加权 ( title^2 )** | ** bq ** | ** bf ** |
| 作用阶段 | 主查询的匹配评分计算阶段 | 主查询后,添加额外查询条件并加权 | 主查询后,通过函数动态调整评分 |
| 评分机制 | 直接影响字段的匹配得分(TF-IDF 等) | 独立计算附加条件的得分,再叠加到总分 | 根据函数计算结果直接调整总分 |
| 适用场景 | 简单字段优先级调整 | 复杂逻辑的条件加权(如促销、库存) | 动态数值计算(如时间衰减、销量加权) |
| 语法灵活性 | 仅支持字段加权 | 支持完整 Lucene 查询语法 | 支持 Solr 函数表达式 |


二、使用场景对比

1. q****中的字段加权 ( title^2**)**
  • 场景:明确提升某个字段的匹配权重。

  • 示例

    bash

    q=title:apple^2 content:apple

    • title 字段匹配 "apple" 的得分是 content 的 2 倍。
2. bq**(Boost Query)**
  • 场景:基于额外条件(如库存状态、分类)提升评分。

  • 示例

    bash

    q=title:apple&bq=in_stock:true^10

    • 主查询匹配 "apple",库存为 true 的文档总分额外增加 10 倍。
3. bf**(Boost Function)**
  • 场景:根据动态数值(如时间、销量)调整评分。

  • 示例

    bash

    q=title:apple&bf=log(sales)^2

    • 销量越高的文档,评分提升越多(按对数计算)。

三、为什么需要 bq****和 bf**?**

1. 解决 q****字段加权的局限性
  • 无法处理复杂条件
    q 中的 ^ 仅能加权字段匹配得分,而 bq 可以附加任意查询条件(如 in_stock:true AND price<100)。
  • 无法动态计算评分
    bf 支持数学函数(如时间衰减 recip(ms(NOW,date))),直接操作评分值。
2. 提升灵活性和性能
  • 独立评分叠加
    bqbf 的评分独立于主查询,可复用缓存结果(如 fq 过滤后的文档集)。
  • 解耦业务逻辑
    将主查询(相关性匹配)与业务规则(如促销优先级)分离,便于维护。

四、为什么需要 eDisMax?

1. 扩展 DisMax 的局限性
  • DisMax 不足
    • 不支持通配符 (*)、模糊搜索 (~)、布尔逻辑 (AND/OR)。
    • 无法使用 bqbf 等高级功能。
  • eDisMax 增强
    • 支持所有 DisMax 功能 + 通配符、模糊搜索、函数查询。
    • 允许更复杂的评分策略(bq/bf)。
2. 典型场景
  • 电商搜索

    bash

    defType=edismax
    q=apple watch
    qf=title^2 content^1
    bq=is_promotion:true^100
    bf=log(sales)^2

    • 主查询匹配关键词,促销商品和高销量商品优先排序。

五、推荐使用策略

  1. 优先使用 qf**+** ^
    明确提升关键字段的匹配权重(如 titlecontent 更重要)。
  2. 复杂条件用 bq
    需要组合多个字段或业务规则时(如 in_stock:true AND category:electronics)。
  3. 动态计算用 bf
    依赖数值、时间等动态因素时(如新发布的文档优先)。
  4. 始终选择 eDisMax
    除非明确需要 DisMax 的极简功能,否则优先使用 eDisMax 的扩展能力。

六、总结

  • **q 字段加权**:简单直接,适合基础相关性优化。
  • **bq**:灵活添加业务规则,适合条件叠加。
  • **bf**:动态数值计算,适合时间、销量等场景。
  • eDisMax:功能全面,是复杂搜索场景的首选解析器。

分面分组的区别

一句话总结

分面 :统计字段分布(如分类数量统计)

分组:按字段将文档归类(如按作者显示所有文章)


1. 分面(Faceting)

作用 :统计字段值的分布情况。
示例:统计商品分类的数量

复制代码
q=*:*&  
facet=true&  
facet.field=category  

返回结果

复制代码
"facet_counts": {  
  "category": {  
    "electronics": 120,  
    "books": 80,  
    "clothing": 200  
  }  
}  

2. 分组(Grouping)

作用 :按字段将文档分组,每组显示指定数量的文档。
示例:按作者分组显示文章(每组最多3篇)

复制代码
q=*:*&  
group=true&  
group.field=author&  
group.limit=3  

返回结果

复制代码
"groups": {  
  "author": {  
    "groups": [  
      {  
        "groupValue": "张三",  
        "doclist": [{文章1}, {文章2}, {文章3}]  
      },  
      {  
        "groupValue": "李四",  
        "doclist": [{文章A}, {文章B}]  
      }  
    ]  
  }  
}  

eDisMax vs DisMax的区别

一句话总结

DisMax :基础版,支持简单字段加权,不支持通配符/模糊搜索。

eDisMax:增强版,支持通配符/模糊搜索/布尔逻辑,推荐优先使用。


1. DisMax 示例
复制代码
q=apple watch&  
defType=dismax&  
qf=title^2 content  

结果

• 搜索 titlecontent 中的 "apple watch"。

不支持 apple*apple~ 等语法。


2. eDisMax 示例
复制代码
q=(apple OR samsung) AND phone~2&  
defType=edismax&  
qf=title^3 brand  

结果

• 搜索 "apple" 或 "samsung",且包含 "phone"(允许2个字符差异)。

• 支持通配符(app*)、模糊搜索(phone~2)、布尔逻辑(AND/OR)。


三、对比总结

|-----------|------------------|------------------|------------|--------------|
| 功能 | 分面(Faceting) | 分组(Grouping) | DisMax | eDisMax |
| 核心用途 | 统计字段分布 | 按字段归类文档 | 简单多字段搜索 | 高级搜索(通配符/模糊) |
| 返回形式 | 统计数值(如数量) | 按组返回文档列表 | 普通文档列表 | 普通文档列表 |
| 典型场景 | 商品分类数量统计 | 按作者显示所有文章 | 基础搜索框 | 复杂搜索(电商/日志) |
| 是否改结构 | 不改结构,只加统计 | 改变结构,分组展示 | - | - |


一句话选型

• 需要统计字段分布 → 分面

• 需要按字段归类文档 → 分组

• 需要通配符/模糊搜索 → eDisMax

相关推荐
gxn_mmf8 分钟前
典籍知识问答模块AI问答功能feedbackBug修改+添加对话名称修改功能
前端·后端·bug
向哆哆1 小时前
Spring Boot快速开发:从零开始搭建一个企业级应用
java·spring boot·后端
泪不是Web妳而流1 小时前
【CTFSHOW_Web入门】命令执行
web安全·网络安全·php·linux命令·rce·命令执行·ctfshow命令执行wp题解
菜鸟、小高2 小时前
Yii2.0 模型规则(rules)详解
php·yii
[email protected]2 小时前
ASP.NET Core 中实现 Markdown 渲染中间件
后端·中间件·asp.net·.netcore
eternal__day7 小时前
Spring Boot 实现验证码生成与校验:从零开始构建安全登录系统
java·spring boot·后端·安全·java-ee·学习方法
海天胜景9 小时前
HTTP Error 500.31 - Failed to load ASP.NET Core runtime
后端·asp.net
海天胜景9 小时前
Asp.Net Core IIS发布后PUT、DELETE请求错误405
数据库·后端·asp.net
深山技术宅10 小时前
在Laravel 12中实现基于parent_id的树状数组
php·laravel
源码云商11 小时前
Spring Boot + Vue 实现在线视频教育平台
vue.js·spring boot·后端