一、pysolr 库概述
1.1 用途
pysolr 是一个专门用于和 Apache Solr 搜索引擎进行交互的 Python 客户端库,它能够让开发者通过简洁的 Python 代码,轻松实现对 Solr 索引的创建、数据的添加、删除、更新以及复杂的查询操作。无论是构建企业级的全文检索系统,还是实现数据分析场景下的快速数据筛选,pysolr 都能提供稳定且高效的支持。

1.2 工作原理
pysolr 底层基于 HTTP/HTTPS 协议与 Solr 服务器进行通信,它将 Python 代码中的操作指令(如查询语句、数据提交指令)封装成符合 Solr API 规范的 HTTP 请求,发送到 Solr 服务器的指定接口(如 /solr/core_name/update 用于数据更新,/solr/core_name/select 用于数据查询),然后接收 Solr 服务器返回的 JSON 格式响应,并将其解析为 Python 中的字典、列表等数据结构,方便开发者直接处理。
1.3 优缺点
优点
- 接口简洁易用,极大降低了 Python 开发者操作 Solr 的门槛,无需手动构造复杂的 HTTP 请求。
- 支持 Solr 的大部分核心功能,包括全文检索、过滤查询、排序、分组统计、高亮显示等。
- 兼容性良好,能够适配不同版本的 Apache Solr,且支持 Python 3.6 及以上的主流 Python 版本。
缺点
- 功能覆盖相较于 Solr 的原生 API 存在少量缺失,部分高级特性(如自定义请求处理器的复杂配置)需要手动扩展 HTTP 请求参数。
- 对大规模数据批量操作的性能优化需要开发者自行调整参数(如批量提交的大小),默认配置下的大批量数据插入效率有待提升。
1.4 License 类型
pysolr 采用的是 BSD 3-Clause 许可证,这是一个宽松的开源许可证,允许开发者自由地使用、修改、分发该库的代码,无论是用于商业项目还是开源项目,都几乎没有限制,只需要保留原作者的版权声明即可。
二、pysolr 安装与环境准备
2.1 安装 pysolr
安装 pysolr 非常简单,推荐使用 Python 的包管理工具 pip 进行安装,在命令行中执行以下命令即可完成安装:
pip install pysolr
该命令会自动从 PyPI 下载并安装最新版本的 pysolr 库及其依赖项(主要依赖 requests 库用于 HTTP 通信)。
2.2 环境依赖确认
- Python 版本:确保你的 Python 环境版本为 3.6 及以上,可以通过
python --version命令查看当前 Python 版本。 - Solr 服务器环境:pysolr 是操作 Solr 的客户端,因此需要先搭建好 Solr 服务器环境。你可以从 Apache Solr 官方网站(https://solr.apache.org/)下载对应版本的 Solr 安装包,按照官方文档完成安装和启动,并创建至少一个 Solr Core(Solr 的核心索引单元)用于后续操作。
- 网络连通性:确保运行 pysolr 代码的机器能够和 Solr 服务器所在的机器互通网络,Solr 默认的 HTTP 端口为 8983,需要保证该端口未被防火墙拦截。
三、pysolr 核心使用方法与代码示例
3.1 连接 Solr 服务器
在使用 pysolr 进行任何操作之前,首先需要创建一个 Solr 客户端实例,建立与 Solr 服务器的连接。核心代码如下:
import pysolr
# 定义 Solr 服务器的基础 URL 和 Core 名称
# 格式为:http://solr_host:solr_port/solr/core_name
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
# 创建 Solr 客户端实例
solr = pysolr.Solr(SOLR_URL, timeout=10)
print("成功连接到 Solr 服务器!")
代码说明
pysolr.Solr()是创建客户端实例的构造函数,第一个参数是 Solr Core 的完整 URL,其中localhost是 Solr 服务器的主机名,8983是默认端口,gettingstarted是 Solr Core 的名称(需要替换为你自己创建的 Core 名称)。timeout参数设置了 HTTP 请求的超时时间(单位为秒),避免因网络问题导致程序长时间阻塞。
3.2 向 Solr 中添加数据
Solr 存储的数据是以文档(Document)为单位的,每个文档是一个键值对的集合,对应 Solr Schema 中定义的字段。我们可以通过 add() 方法向 Solr 中添加单个或多个文档。
3.2.1 添加单个文档
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 定义一个 Solr 文档,字段需要和 Solr Schema 中的定义一致
document = {
"id": "book_001", # id 字段是 Solr 的默认唯一标识字段,必填
"title": "Python编程:从入门到实践",
"author": "埃里克·马瑟斯",
"publisher": "人民邮电出版社",
"publish_date": "2020-01-01",
"price": 59.8,
"tags": ["Python", "编程", "入门"]
}
# 添加文档到 Solr
solr.add([document])
# 提交更改,确保数据被持久化到索引中
solr.commit()
print("单个文档添加成功!")
3.2.2 批量添加多个文档
当需要添加大量数据时,批量添加的效率远高于逐个添加,代码示例如下:
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 定义多个文档的列表
documents = [
{
"id": "book_002",
"title": "流畅的Python",
"author": "卢西亚诺·拉马略",
"publisher": "人民邮电出版社",
"publish_date": "2017-05-01",
"price": 129.0,
"tags": ["Python", "进阶", "编程思想"]
},
{
"id": "book_003",
"title": "Python数据分析与挖掘实战",
"author": "张良均",
"publisher": "机械工业出版社",
"publish_date": "2019-03-01",
"price": 79.0,
"tags": ["Python", "数据分析", "挖掘"]
},
{
"id": "book_004",
"title": "深度学习入门:基于Python的理论与实现",
"author": "斋藤康毅",
"publisher": "人民邮电出版社",
"publish_date": "2018-07-01",
"price": 69.0,
"tags": ["Python", "深度学习", "AI"]
}
]
# 批量添加文档
solr.add(documents, batch_size=2) # batch_size 表示每次提交的文档数量
# 提交更改
solr.commit()
print("批量文档添加成功!")
代码说明
add()方法接收一个文档列表作为参数,batch_size参数可以控制每次向 Solr 提交的文档数量,当文档数量较多时,合理设置batch_size可以避免单次请求数据量过大导致的失败。commit()方法用于提交更改,Solr 在接收到add请求后,会先将数据存入内存,只有执行commit操作后,数据才会被写入磁盘索引,并且才能被查询到。
3.3 从 Solr 中删除数据
pysolr 支持通过文档 ID、查询条件等方式删除 Solr 中的数据,常用的删除方法有 delete() 和 delete_by_query()。
3.3.1 通过 ID 删除单个文档
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 通过文档 ID 删除
solr.delete(id="book_001")
# 提交更改
solr.commit()
print("通过ID删除文档成功!")
3.3.2 通过查询条件删除多个文档
如果需要删除满足特定条件的一批文档,可以使用 delete_by_query() 方法,代码示例如下:
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 删除 publisher 为"机械工业出版社"的所有文档
solr.delete_by_query("publisher:机械工业出版社")
# 提交更改
solr.commit()
print("通过查询条件删除文档成功!")
3.3.3 删除所有文档
如果需要清空整个 Solr Core 的数据,可以使用通配符查询条件 *:*,代码如下:
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 删除所有文档
solr.delete_by_query("*:*")
# 提交更改
solr.commit()
print("所有文档删除成功!")
代码说明
delete(id="xxx")方法用于删除指定 ID 的文档,ID 是 Solr 文档的唯一标识。delete_by_query(query)方法接收一个 Solr 查询语句作为参数,会删除所有满足该查询条件的文档,使用时需要格外谨慎,避免误删数据。
3.4 查询 Solr 中的数据
查询是 Solr 的核心功能,pysolr 提供了 search() 方法来执行各种查询操作,支持全文检索、过滤、排序、分页、高亮等多种功能。
3.4.1 基础全文检索
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 先添加一些测试数据,方便查询
test_docs = [
{
"id": "book_002",
"title": "流畅的Python",
"author": "卢西亚诺·拉马略",
"publisher": "人民邮电出版社",
"publish_date": "2017-05-01",
"price": 129.0,
"tags": ["Python", "进阶", "编程思想"]
},
{
"id": "book_003",
"title": "Python数据分析与挖掘实战",
"author": "张良均",
"publisher": "机械工业出版社",
"publish_date": "2019-03-01",
"price": 79.0,
"tags": ["Python", "数据分析", "挖掘"]
}
]
solr.add(test_docs)
solr.commit()
# 基础全文检索:搜索标题中包含"Python"的文档
results = solr.search("title:Python")
# 处理查询结果
print(f"查询到 {len(results)} 条结果:")
for result in results:
print(f"ID: {result['id']}")
print(f"标题: {result['title']}")
print(f"作者: {result['author']}")
print(f"价格: {result['price']}")
print("-" * 50)
3.4.2 带过滤条件的查询
在实际应用中,我们经常需要在全文检索的基础上,添加过滤条件来缩小查询范围,例如过滤价格区间、出版社等,代码示例如下:
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 搜索标题包含"Python",且价格在 50-100 之间,出版社为"人民邮电出版社"的文档
# q 参数是查询语句,fq 参数是过滤条件(可以是多个)
results = solr.search(
q="title:Python",
fq=[
"price:[50 TO 100]", # 价格区间过滤,闭区间
"publisher:人民邮电出版社"
]
)
print(f"过滤查询到 {len(results)} 条结果:")
for result in results:
print(f"ID: {result['id']}")
print(f"标题: {result['title']}")
print(f"价格: {result['price']}")
print(f"出版社: {result['publisher']}")
print("-" * 50)
3.4.3 带排序和分页的查询
当查询结果较多时,分页和排序功能是必不可少的,pysolr 支持通过 sort、start、rows 参数来实现,代码示例如下:
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 先添加更多测试数据
more_docs = [
{
"id": "book_005",
"title": "Python爬虫开发与项目实战",
"author": "范传辉",
"publisher": "机械工业出版社",
"publish_date": "2020-01-01",
"price": 65.0,
"tags": ["Python", "爬虫"]
},
{
"id": "book_006",
"title": "Python Web开发实战",
"author": "陶俊杰",
"publisher": "清华大学出版社",
"publish_date": "2018-10-01",
"price": 89.0,
"tags": ["Python", "Web开发"]
}
]
solr.add(more_docs)
solr.commit()
# 搜索标题包含"Python"的文档,按价格降序排序,分页获取第1页(从0开始),每页3条
results = solr.search(
q="title:Python",
sort="price desc", # desc 降序,asc 升序
start=0, # 起始位置
rows=3 # 每页显示的条数
)
print(f"分页查询到 {len(results)} 条结果:")
for result in results:
print(f"ID: {result['id']}")
print(f"标题: {result['title']}")
print(f"价格: {result['price']}")
print("-" * 50)
# 获取总记录数
print(f"符合条件的总记录数: {results.hits}")
3.4.4 高亮显示查询结果
高亮显示可以让查询结果中匹配的关键词以特殊样式呈现,提升用户体验,pysolr 支持通过 hl 相关参数实现高亮功能,代码示例如下:
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 搜索标题包含"Python"的文档,并高亮显示标题中的关键词
results = solr.search(
q="title:Python",
hl=True, # 开启高亮功能
hl_fl="title", # 指定需要高亮的字段
hl_simple_pre="<em>", # 高亮前缀
hl_simple_post="</em>" # 高亮后缀
)
print(f"高亮查询到 {len(results)} 条结果:")
for result in results:
print(f"ID: {result['id']}")
# 获取高亮后的标题
highlighted_title = result.highlighting.get(result['id'], {}).get('title', [result['title']])[0]
print(f"高亮标题: {highlighted_title}")
print(f"作者: {result['author']}")
print("-" * 50)
代码说明
hl=True表示开启高亮功能,hl_fl指定需要进行高亮处理的字段。hl_simple_pre和hl_simple_post分别设置高亮的前缀和后缀,通常用于 HTML 页面展示,让关键词以斜体、加粗等样式显示。result.highlighting中存储了高亮后的字段内容,需要通过文档 ID 来获取对应字段的高亮结果。
3.5 更新 Solr 中的数据
Solr 的数据更新可以通过 add() 方法结合文档 ID 实现,因为 Solr 会根据 ID 进行覆盖更新,代码示例如下:
import pysolr
SOLR_URL = "http://localhost:8983/solr/gettingstarted"
solr = pysolr.Solr(SOLR_URL, timeout=10)
# 定义需要更新的文档,ID 为已存在的文档 ID
updated_document = {
"id": "book_002",
"title": "流畅的Python(第2版)", # 更新标题
"author": "卢西亚诺·拉马略",
"publisher": "人民邮电出版社",
"publish_date": "2022-01-01", # 更新出版日期
"price": 149.0, # 更新价格
"tags": ["Python", "进阶", "编程思想", "第2版"] # 更新标签
}
# 通过 add 方法实现更新,Solr 会根据 ID 覆盖原有文档
solr.add([updated_document])
solr.commit()
print("文档更新成功!")
# 验证更新结果
result = solr.search(q="id:book_002")
for doc in result:
print(f"更新后的标题: {doc['title']}")
print(f"更新后的价格: {doc['price']}")
print(f"更新后的标签: {doc['tags']}")
代码说明
Solr 没有专门的更新方法,而是通过“先删除后添加”的逻辑实现更新,当使用 add() 方法提交一个已存在 ID 的文档时,Solr 会自动删除原有 ID 的文档,然后添加新的文档内容,从而实现更新效果。
四、pysolr 实际应用案例:构建简单的图书检索系统
4.1 案例需求
我们需要构建一个简单的图书检索系统,实现以下功能:
- 批量导入图书数据到 Solr。
- 支持按书名、作者、出版社进行全文检索。
- 支持按价格区间过滤检索结果。
- 支持对检索结果按价格排序和分页。
- 支持高亮显示检索关键词。
4.2 案例代码实现
import pysolr
from typing import List, Dict, Optional
class BookSearchSystem:
def __init__(self, solr_url: str, timeout: int = 10):
"""
初始化图书检索系统
:param solr_url: Solr Core 的 URL
:param timeout: HTTP 请求超时时间
"""
self.solr = pysolr.Solr(solr_url, timeout=timeout)
def import_books(self, books: List[Dict]) -> None:
"""
批量导入图书数据到 Solr
:param books: 图书数据列表
"""
if not books:
print("没有需要导入的图书数据!")
return
try:
self.solr.add(books, batch_size=5)
self.solr.commit()
print(f"成功导入 {len(books)} 本图书数据!")
except Exception as e:
print(f"导入图书数据失败:{e}")
def search_books(
self,
keyword: str,
field: str = "*",
min_price: Optional[float] = None,
max_price: Optional[float] = None,
sort_by: str = "price asc",
page: int = 1,
page_size: int = 3,
highlight: bool = True
) -> pysolr.Results:
"""
检索图书数据
:param keyword: 检索关键词
:param field: 检索的字段,* 表示所有字段
:param min_price: 最低价格过滤条件
:param max_price: 最高价格过滤条件
:param sort_by: 排序方式,如 price desc
:param page: 页码,从 1 开始
:param page_size: 每页显示的条数
:param highlight: 是否开启高亮
:return: 检索结果
"""
# 构建查询语句
if field == "*":
query = f"{keyword}"
else:
query = f"{field}:{keyword}"
# 构建过滤条件
filter_queries = []
if min_price is not None and max_price is not None:
filter_queries.append(f"price:[{min_price} TO {max_price}]")
elif min_price is not None:
filter_queries.append(f"price:[{min_price} TO *]")
elif max_price is not None:
filter_queries.append(f"price:[* TO {max_price}]")
# 计算分页参数
start = (page - 1) * page_size
# 构建高亮参数
hl_params = {}
if highlight:
hl_params = {
"hl": True,
"hl_fl": field if field != "*" else "title,author,publisher",
"hl_simple_pre": "<strong>",
"hl_simple_post": "</strong>"
}
# 执行查询
results = self.solr.search(
q=query,
fq=filter_queries,
sort=sort_by,
start=start,
rows=page_size,
**hl_params
)
return results
def display_results(self, results: pysolr.Results) -> None:
"""
展示检索结果
:param results: 检索结果对象
"""
if not results:
print("没有查询到符合条件的图书!")
return
print(f"\n共查询到 {results.hits} 本符合条件的图书,当前显示第 {(results.start // results.rows) + 1} 页:")
print("=" * 80)
for idx, result in enumerate(results, start=1):
book_id = result['id']
# 获取高亮内容
highlighting = result.highlighting.get(book_id, {})
title = highlighting.get('title', [result.get('title', '未知标题')])[0]
author = highlighting.get('author', [result.get('author', '未知作者')])[0]
publisher = highlighting.get('publisher', [result.get('publisher', '未知出版社')])[0]
price = result.get('price', 0.0)
print(f"[{idx}] ID: {book_id}")
print(f"标题: {title}")
print(f"作者: {author}")
print(f"出版社: {publisher}")
print(f"价格: {price} 元")
print("-" * 80)
# 测试图书检索系统
if __name__ == "__main__":
# Solr Core URL
SOLR_CORE_URL = "http://localhost:8983/solr/gettingstarted"
# 初始化系统
book_system = BookSearchSystem(SOLR_CORE_URL)
# 准备测试图书数据
test_books = [
{"id": "b1001", "title": "Python编程:从入门到实践", "author": "埃里克·马瑟斯", "publisher": "人民邮电出版社", "price": 59.8, "tags": ["Python", "入门"]},
{"id": "b1002", "title": "流畅的Python", "author": "卢西亚诺·拉马略", "publisher": "人民邮电出版社", "price": 129.0, "tags": ["Python", "进阶"]},
{"id": "b1003", "title": "Python数据分析与挖掘实战", "author": "张良均", "publisher": "机械工业出版社", "price": 79.0, "tags": ["Python", "数据分析"]},
{"id": "b1004", "title": "深度学习入门:基于Python的理论与实现", "author": "斋藤康毅", "publisher": "人民邮电出版社", "price": 69.0, "tags": ["Python", "AI"]},
{"id": "b1005", "title": "Python爬虫开发与项目实战", "author": "范传辉", "publisher": "机械工业出版社", "price": 65.0, "tags": ["Python", "爬虫"]},
{"id": "b1006", "title": "Java编程思想", "author": "布鲁斯·埃克尔", "publisher": "机械工业出版社", "price": 109.0, "tags": ["Java", "进阶"]},
{"id": "b1007", "title": "Python Web开发实战", "author": "陶俊杰", "publisher": "清华大学出版社", "price": 89.0, "tags": ["Python", "Web"]},
{"id": "b1008", "title": "数据结构与算法分析:Python语言描述", "author": "马克·艾伦·维斯", "publisher": "机械工业出版社", "price": 75.0, "tags": ["Python", "算法"]}
]
# 批量导入图书数据
book_system.import_books(test_books)
# 测试检索功能:搜索标题包含"Python",价格在 50-100 之间的图书,按价格降序排序,第1页,每页3条
search_results = book_system.search_books(
keyword="Python",
field="title",
min_price=50.0,
max_price=100.0,
sort_by="price desc",
page=1,
page_size=3,
highlight=True
)
# 展示检索结果
book_system.display_results(search_results)
# 测试检索功能:搜索作者包含"张良均"的图书
print("\n\n===== 按作者检索 =====")
author_results = book_system.search_books(keyword="张良均", field="author")
book_system.display_results(author_results)
4.3 案例运行说明
- 运行该代码前,需要确保 Solr 服务器已启动,且对应的 Core 已创建。
- 代码中定义了
BookSearchSystem类,封装了图书数据的导入和检索功能,便于复用和维护。 - 测试部分首先初始化系统,然后导入测试图书数据,接着执行两次检索操作,分别按标题和作者检索,并展示结果。
- 检索结果中,匹配的关键词会被
<strong>标签包裹,在 HTML 页面中展示时会呈现为加粗样式。
五、pysolr 相关资源链接
- PyPI 地址:https://pypi.org/project/pysolr
- Github 地址:https://github.com/django-haystack/pysolr
- 官方文档地址:https://pysolr.readthedocs.io/en/latest/
关注我,每天分享一个实用的Python自动化工具。

