type
Post
status
Published
date
Apr 12, 2020 15:02
slug
summary
本文全面介绍Apache Solr全文搜索引擎的使用方法,涵盖Solr的核心概念、安装部署、查询操作(基本查询、统计、分组、多维统计、高亮)、数据修改删除、字段类型配置,以及与HBase集成实现实时索引的完整实践方案。适合需要构建企业级搜索系统的开发者。
tags
Solr
HBase
category
Data Engineering
icon
password
wordCount
5614
前言
在海量数据时代,如何快速检索信息成为每个开发者必须面对的挑战。想象一下,你有数百万条商品数据,用户输入"红色连衣裙",系统需要在毫秒级返回最相关的结果——这就是全文搜索引擎的价值所在。
核心要点
本文将带你全面了解Apache Solr搜索引擎:
- 基础概念:理解Solr的工作原理和核心特性
- 安装部署:手把手完成Solr环境搭建
- 实战查询:掌握基本查询、统计、分组、高亮等核心功能
- 数据管理:学会增删改操作和字段配置
- 集成实践:将Solr与HBase结合实现实时索引
什么是Solr
Solr是基于Apache Lucene构建的搜索服务器,Apache Lucene是基于Java的开源信息检索库。它旨在驱动功能强大的文档检索应用程序-无论您需要根据用户的查询向其提供数据的任何地方,Solr都能为您服务
- Solr能为你想要搜索的数据建立索引,提高搜索效率
- Solr能配置各种分词器,如英文分词器,中文分词器。分词器能将你输入的搜索文本切分成几个词,然后搜索出最匹配这几个词的数据。例如中文分词器(不同类别的中文分词分词结果不一样),输入“我是中国人”,Solr会将这句话切分为“我”,“是”,“中国人”去进行搜索。
- Solr支持分布式搜索,将搜索数据分布在数个solr服务器上,称之为SolrCloud集群。当Solr节点接收到搜索请求时,该请求将在后台路由到碎片的副本,该碎片是要搜索的集合的一部分。
Solr安装
- 下载Solr安装包 可从Solr网站获得Solr。下载最新版本 有三个单独的程序包:
- solr-8.5.0.tgz 用于Linux / Unix / OSX系统
- solr-8.5.0.zip 用于Microsoft Windows系统
- solr-8.5.0-src.tgz软件包Solr源代码。如果您想在Solr上进行开发而不使用官方的Git存储库,这将很有用。
- 解压solr
bash $ cd ~/ $ tar zxf solr-8.5.0.tgz安装Solr之后,您将在其中看到以下目录和文件: - bin/ 该目录包含几个重要的脚本,这些脚本将使使用Solr更加容易。
- solr和solr.cmd 这是Solr的控制脚本,也称为bin/solr(* nix)/ bin/solr.cmd(Windows)。该脚本是启动和停止Solr的首选工具。在以SolrCloud模式运行时,您还可以创建集合或核心,配置身份验证并使用配置文件。
- post 它提供了用于发布内容到Solr一个简单的命令行界面。
- solr.in.sh和solr.in.cmd 这些分别是* nix和Windows系统的属性文件。在此配置Java,Jetty和Solr的系统级属性。使用bin/solr/时bin/solr.cmd,可以覆盖许多设置,但这使您可以将所有属性设置在一个位置。
- install_solr_services.sh 该脚本在* nix系统上用于将Solr作为服务安装。在将Solr投入生产一节中对此进行了详细描述。
- contrib/ Solr的contrib目录包括用于Solr的特殊功能的附加插件。
- dist / 该dist目录包含主要的Solr .jar文件。
- docs / 该docs目录包含指向Solr的在线Javadocs的链接。
- example/ 该example目录包括几种类型的示例,这些示例演示了各种Solr功能。有关此目录中内容的更多详细信息,请参见下面的Solr示例部分。
- licenses/ 该licenses目录包含Solr使用的第三方库的所有许可证。
- server/ 该目录是Solr应用程序的心脏所在的位置。此目录中的自述文件提供了详细的概述,但以下是一些要点:
- Solr’s Admin UI (server/solr-webapp)
- Jetty libraries(server/lib)
- 日志文件(server/logs)和日志配置(server/resources)。有关如何自定义Solr的默认日志记录的更多详细信息,请参阅配置日志记录部分。
- 样本配置集(server/solr/configsets)
- 启动solr服务
如果您正在运行Windows,则可以通过运行bin.cmd来启动Solr 。
- 检测solr是否在运行
- 打开浏览器 访问 http://localhost:8983/solr/

Solr使用
打开sorl页面,我们可以看到如下的图所示的页面:

左侧为操作菜单,从上往下依次是:
- 仪表盘(Dashboard):
在仪表盘页面能看到一些系统的基本信息,如启动时间,版本号,jvm的配置,磁盘剩余空间
- Log日志(Logging):
可以查看各级别的日志
- 云集群管理(Cloud)
集群的管理界面,看到所有的节点状态,zookeeper的状态。
- 数据源管理(Collections)
数据源的管理界面
- 配置项查看(Java Properties)
能看见java的所有配置项
- 线程转储(Thread dump)
一个诊断Java应用问题的工具,Thread dumps出来的信息包含线程;线程的运行状态、标识和调用的堆栈;调用的堆栈包含完整的类名,所执行的方法
- 建议(Suggestions):
对于集群的一些建议
- 选择数据源:
选择数据源后会出现分词,查询等操作
- 选择核心
每个核心都是solr的一个实例,这里可以查看solr的核心
查询
选择数据源后,会出现query操作选项

左侧为查询的参数,右侧为查询结果,下面将详细介绍参数的使用

基本查询
参数名 | 默认 | 类型 | 说明 | 例子 |
fl | N/A | string | 查询的字段,多个字段用逗号隔开 | 查询Id,name字段:&fl=id,name |
q | N/A | string | Where条件,高亮字段放这里 | 1.AND: &q=id:1 AND (name=2)2.OR:&q=id:1 OR name=23.查询id>1并且id<=3&q=id:(1 TO 3]4.查id in (1,2,3)&q=(id:1 OR id:2 OR id:3) |
fq | N/A | string | Where条件,非高亮字段放这里 | 参考q |
sort | N/A | string | 排序字段 | &sort=id desc |
start | N/A | int | offset | &start=0 |
rows | N/A | int | limit | &rows=10 |
indent | False | Boolean | 返回的结果是否缩进,默认关闭,用 indent=true | on 开启,一般调试json,php,phps,ruby输出才有必要用这个参数。 |
wt | xml | String | 指定查询输出结构格式,默认为“xml”。在solrconfig.xml中定义了查询输出格式:xml、json、python、ruby、php、phps、custom。 | &wt=xml&wt=json |
omitHeader | False | Boolean | 设置是否忽略查询结果返回头信息 | &omitHeader=false&omitHeader=true |
debugQuery | False | Boolean | 设置返回结果是否显示Debug信息。 | &debugQuery=true&debugQuery=false |
timeAllowed | N/A | int | 定义要处理的查询的时间。如果处理超时,只返回部分信息。单位毫秒 | &timeAllowed=100 |
检索运算
- “:” 指定字段查指定值,如返回所有值:
- “?” 表示单个任意字符的通配
- “” 表示多个任意字符的通配(不能在检索的项开始使用或者?符号)
- “ ~ ” 表示模糊检索,如检索拼写类似于”roam”的项这样写:roam~ 将找到形如foam和roams的单词;roam~ 0.8,检索返回相似度在0.8以上的记录。
- AND、|| 布尔操作符
- OR、&& 布尔操作符
- NOT、!、-(排除操作符不能单独与项使用构成查询) -“+” 存在操作符,要求符号”+”后的项必须在文档相应的域中存在²
- ( ) 用于构成子查询
- [] 包含范围检索,如检索某时间段记录,包含头尾,date:[201507 TO 201510]
- {} 不包含范围检索,如检索某时间段记录,不包含头尾date:{201507 TO 201510}
统计查询
参数名 | 默认 | 类型 | 说明 | 例子 |
stats | False | Boolean | 是否开启统计 | &stats=true&stats=false |
stats.field | N/A | String | 需要统计的字段 | &stats.field=id |
stats.facet | N/A | String | 返回统计的结果集 min:最小值 max:最大值 sum:总和 count: 记录数,也就是多少行记录 missing: 结果集中,有多少条记录是空值 sumOfSquares: 平方和(x1^2 + x22+xn2) mean:平均数(x1+x2+xn)/n stddev: 标准差 | &stats.facet=idCount |
例:按id统计
参数:
结果:

分组查询
参数名 | 默认 | 类型 | 说明 | 例子 |
Group | False | Boolean | 开启分组查询 | &group=true&group=false |
group.field | N/A | String | 分组字段 | &group.field=id |
group.func | N/A | String | 指定聚合函数,avg:求平均值 AVG(DISTINCT | ALL |
group.query | N/A | String | 查询语句,查询分组后集合,用法和q与fq一样 | &group.query=address_id:1000 |
group.limit | 1 | Int | 每组返回多数条结果,默认1 | &group.limit=200 |
group.offset | 0 | Int | 指定每组结果开始位置/偏移量 | &group.offset=10 |
group.sort | N/A | String | 分组结果排序字段 | &group.sort=id |
group.format | grouped | String | 两值grouped与simple.设置为simple可以使得结果以单一列表形式返回 | &group.format=simple&group.format=grouped |
group.main | Fals | Boolean | group.main=true返回每个分组的第一条记录信息(没有分组的详细信息) | &group.main=true&group.main=false |
group.ngroups | False | Boolean | 设为true时,Solr将返回分组数量,默认fasle | &group.ngroups=false&group.ngroups=true |
group.truncate | False | Boolean | 设为true时,facet数量将基于group分组中匹相关性高的文档,默认fasle | &group.truncate=true&group.truncate=false |
group.cache.percent | 0 | int | 取值0-100,设为大于0时,表示缓存结果,默认为0。该项对于布尔查询,通配符查询,模糊查询有改善,却会减慢普通词查询。 | &group.cache.percent=0&group.cache.percent=100 |
例:按id分组
参数:
结果:

多维统计
参数名 | 默认 | 类型 | 说明 | 例子 |
facet | False | Boolean | 开启facet,相当于group by后再count(*)的集合 | &facet=true,facet=false |
facet.field | N/A | String | 各自分组的字段并返回count(*) | &facet.field=id,name |
facet.prefix | N/A | String | 表示Facet字段值的前缀 | 对cpu字段进行Facet查询,返回的cpu都是以”Intel”开头的,”AMD”开头的cpu型号将不会被统计在内: &facet.field=cpu&facet.prefix=Intel |
facet.sort | N/A | Boolean | 表示Facet字段值以哪种顺序返回. | 可接受的值为true(count) |
facet.limit | 100 | int | 限制Facet字段返回的结果条数,默认值为100.如果此值为负数,表示不限制 | &facet.limit=10 |
facet.offset | 0 | int | 返回结果集的偏移量,默认为0 | &facet.offset=0 |
facet.mincount | 0 | int | 限制了Facet字段值的最小count | &facet.mincount=10 |
facet.missing | N/A | Boolean | 统计字段值为Null数量 | &facet.missing=on, &facet.missing=true |
facet.method | fc | String | enum适用于字段值比较少的情况,比如字段类型为布尔型,或者字段表示中国的所有省份.Solr会遍历该字段的所有取值,并从filterCache里为每个值分配一个filter(这里要求solrconfig.xml里对filterCache的设置足够大).然后计算每个filter与主查询的交集.fc(表示Field Cache)适用于字段取值比较多,但在每个文档里出现次数比较少的情况.Solr会遍历所有的文档,在每个文档内搜索Cache内的值,如果找到就将Cache内该值的count加1. | &facet.method=enum.&facet.method=fc |
facet.enum.cache.minDf | 0 | int | 当facet.method=enum时,此参数其作用,minDf表示minimum document frequency.也就是文档内出现某个关键字的最少次数.该参数默认值为0.设置该参数可以减少filterCache的内存消耗,但会增加总的查询时间(计算交集的时间增加了).如果设置该值的话,官方文档建议优先尝试25-50内的值. | &facet.enum.cache.minDf=30 |
facet.date | N/A | String | 该参数表示需要进行Date Facet的字段名,与facet.field一样,该参数可以被设置多次,表示对多个字段进行Date Facet. | &facet.date=birthday |
facet.date.start | N/A | Date | 与facet.date一起使用,起始时间,时间的一般格式为1995-12-31T23:59:59Z,另外可以使用”NOW”,”YEAR”,”MONTH”等等 &facet.date.start=2014-01-00T09:15:00Z | |
facet.date.end | N/A | Date | 与facet.date一起使用,起始时间,时间的一般格式为1995-12-31T23:59:59Z,另外可以使用”NOW”,”YEAR”,”MONTH”等等 &facet.date.end=2014-01-00T09:15:00Z | |
N/A | String | 时间间隔,如果start为2009-1-1,end为2010-1-1.gap设置为”+1MONTH”表示间隔1个月,那么将会把这段时间划分为12个间隔段.注意”+”因为是特殊字符所以应该用”%2B”代替. &facet.date.gap=%2B1MONTH | ||
facet.date.other | N/A | String | 取值范围为before | after |
facet.date.hardend | N/A | Boolean | 取值可以为true | false,默认为false.它表示gap迭代到end处采用何种处理.举例说明start为2009-1-1,end为2009-12-25,gap为”+1MONTH”,hardend为false的话最后一个时间段为2009-12-1至2010-1-1;hardend为true的话最后一个时间段为2009-12-1至2009-12-25. |
facet.pivot | N/A | String | 多维统计 | 统计各个电影类别的各导演的电影数:&facet.pivot=category,author |
例子1
查询 2014-01到2014-12的birthday,按每月分区
参数
结果
例子2
按电影类别分类,再统计类别基础上各导演的电影数
参数:
结果:

高亮
参数名 | 默认 | 类型 | 说明 | 例子 |
hl | false | Boolean | 是否开启高亮 | &hl=true&hl=false |
hl.fl | N/A | String | 设定高亮显示的字段,用空格或逗号隔开的字段列表。要启用某个字段的highlight功能,就得保证该字段在schema中是stored。如果该参数未被给出,那么就会高亮默认字段 standard handler会用df参数,dismax字段用qf参数。你可以使用星号去方便的高亮所有字段。如果你使用了通配符,那么要考虑启用hl.requiredFieldMatch选 | &hl.fl=id |
hl.requireFieldMatch | False | Boolean | 如果置为true,除非用hl.fl指定了该字段,查询结果才会被高亮 | &hl.requireFieldMatch=ture&hl.requireFieldMatch=false |
hl.usePhraseHighlighter | False | Boolean | 如果一个查询中含有短语(引号框起来的)那么会保证一定要完全匹配短语的才会被高亮 | &hl.usePhraseHighlighter=true&hl.usePhraseHighlighter=false |
hl.highlightMultiTerm | False | Boolean | 如果使用通配符和模糊搜索,那么会确保与通配符匹配的term会高亮。默认为false,同时hl.usePhraseHighlighter要为true | &hl.highlightMultiTerm=true&hl.highlightMultiTerm==false |
hl.fragsize | 100 | Int | 返回的最大字符数。默认是100.如果为0,那么该字段不会被fragmented且整个字段的值会被返回 | &hl.fragsize=0&hl.fragsize=100 |
修改与删除
可以通过api或者web界面操作:
- api
Api:http://hdp-e-1.data.dc.zjft.com:8886/solr/ranger_audits/update
Method:post
Request-Handler (qt): 只能是/update
Document Type:文档类型
Document:文档
Overwrite: 为true,说明如果id重复则覆盖以前的值;为false说明如果id重复不覆盖以前的
- 界面操作 选择数据源后,会出现documents操作选项


修改(新增)文档

删除文档

Document:
commit不能少,表示提交
配置solr字段类型
solr在摄取数据前应该配置好字段类型,修改后仅对新数据生效,旧数据不会生效,再创建集合后就应该马上配置好
- 选colletion的schema

- 点击AddFile
- AddFile:添加字段
- Add Dynamic Filed:添加通配字段,即可以使用通配符来指定字段(如 patient_* 那么以patient_开头的字段都会使用这个配置)
- Add copy filed :添加重复数据字段
- 以通配字段为例,以map_patient_case.开头的字段,都匹配成string类型,并且可以排序与索引

集成HBase
solr配合Hbase-indexer,通过xml文件指定需要索引的表与字段,当数据进入hbase的相应的表后,数据就会被索引到Solr搜索引擎。建立Hbase与Solr索引之前需要设计好字段的类型并且在Solr上配置好

安装Hbase-indexer
HBase Indexer项目为存储在HBase中的内容提供索引(通过Solr)。它提供了一种定义索引规则的灵活且可扩展的方式,并且可以按比例缩放。索引是异步执行的,因此不会影响HBase上的写吞吐量。SolrCloud用于存储实际索引,以确保索引的可伸缩性。
- 获取HBase索引器 签出代码并构建tar.gz发行版
- 接下来,解压缩tar.gz发行版(在下面的示例中,将其解压缩到$ HOME目录下)
- 配置HBase索引器 在hbase-indexer目录中,编辑文件conf/hbase-indexer-site.xml并配置ZooKeeper连接字符串(两次,一次用于hbase-indexer,一次用于hbase,或者您也可以将其复制hbase-site.xml到conf目录)
如果尚未全局定义JAVA_HOME,并且bin / hbase-indexer脚本会抱怨找不到Java,则可以在脚本中设置JAVA_HOME conf/hbase-indexer-env.sh
- 配置HBase 为了使用HBase索引器,必须在HBase中启用复制。还可以设置许多其他HBase设置来优化HBase索引器的工作。
将以下设置添加到所有HBase区域服务器上的hbase-site.xml配置中,然后重新启动HBase
- 将索引器jar添加到HBase HBase索引器包含两个必须在HBase的类路径中的jar文件。将它们从解压缩的hbase-indexer安装的lib目录复制到每个区域服务器的HBase的lib目录中。
- 测试habse-indexer 进入habase-indexer目录,进入bin目录
上面命令将输出目前索引集合
solr索引Hbase数据
- habse需要打开备份 进入hbase命令模式后,输入下面代码,table换成需要索引的表名
- solr instance设置auto commit(已经设置,无需重复设置)
修改成下面内容
改了配置后重启solrinstance, 然后需要删除collection,重新创建才有效!!!
- solr创建集合 下面语句创建了一个collertion1的集合
sudo -u infra-solr /usr/lib/ambari-infra-solr/bin/solr create_collection -c collection1 -shards 1 -replicationFactor 1- 启动habse-index(已经启动可跳过) 进入hbase-indexer目录
bash nohup bin/hbase-indexer server >>/var/log/hbase-indexer.log 2>&1 &- 编写indexer的schema
- name为solr字段名
- value为hbase字段名,支持通配符
- type为字段类型 非宽表例子hkpmi_patient_data.xml
xml <?xml version="1.0"?> <indexer table="hkpmi_all_wide"> <field name="patient_id" value="f1:patient_data.patient_id" type="string"/> <field name="process_dtm" value="f1:patient_data.process_dtm" type="string"/> <field name="patient_name" value="f1:patient_data.patient_name" type="string"/> </indexer>
宽表例子hkpmi_patient_nok_wide.xml
xml <?xml version="1.0"?> <indexer table="hkpmi_all_wide" mapping-type="column" unique-key-formatter="com.ngdata.hbaseindexer.uniquekey.StringUniqueKeyFormatter"> <field name="patient_id" value="f1:patient_nok.patient_id" type="string"/> <field name="p1" value="f1:patient_nok.p1_*" type="string"/> <field name="p2" value="f1:patient_nok.p2_*" type="string"/> <field name="process_dtm" value="f1:patient_nok.process_dtm_*" type="string"/> </indexer>一个hbase table可以建多个indexer,每个indexer就是合并前的表
indexer的id需要指定为该表的主键,如果没有主键,需要造一个出来,否则无法更新或删除。
- 添加索引 根据schema创建indexer
- n:索引名
- c:schema文件路径
- cp:额外参数,后面带参数名与参数值
- solr.zk:zookeeper集群ip地址,逗号分隔
- solr.collection:指定同步到哪个solr集合
$ZK_HOST 为zookeeper集群的ip
$ROOT_DIR为habase目录路径
运行下面脚本创建一个宽表与一个非宽表
参数解析:
- 删除索引 $ROOT_DIR为habse-indexer目录
写在最后
Solr作为成熟的企业级搜索解决方案,在电商、内容平台、日志分析等场景中扮演着关键角色。通过本文的学习,你已经掌握了从安装到实战的完整技能链。
未来展望:随着数据规模持续增长,Solr的分布式架构SolrCloud将成为必然选择。结合机器学习的智能排序、向量搜索等新特性,也让Solr在AI时代依然保持强大竞争力。建议在实际项目中:
- 根据业务特点选择合适的分词器
- 合理设计字段类型和索引策略
- 利用facet和统计功能实现多维分析
- 在生产环境中监控查询性能并持续优化
搜索的艺术在于平衡精准度与性能,而Solr给了我们足够的工具来实现这种平衡。
