第4章:创建第一个全文索引
4.1 索引创建的基本流程
4.1.1 创建索引的完整流程
创建一个 Whoosh 全文索引通常包含以下步骤:
1. 导入必要的模块
↓
2. 定义 Schema(字段结构)
↓
3. 指定索引目录
↓
4. 创建索引对象
↓
5. 获取 Writer 对象
↓
6. 添加文档数据
↓
7. 提交(commit)保存索引4.1.2 目录准备
索引需要存储在文件系统中,因此需要先准备好目录:
import os
# 确保索引目录存在
index_dir = "my_index"
if not os.path.exists(index_dir):
os.makedirs(index_dir)4.1.3 创建与打开索引
Whoosh 提供两种方法操作索引:
1. 创建新索引
from whoosh.index import create_in
ix = create_in(index_dir, schema)2. 打开已有索引
from whoosh.index import open_dir
ix = open_dir(index_dir)3. 检查索引是否存在
from whoosh.index import exists_in
if exists_in(index_dir):
ix = open_dir(index_dir)
else:
ix = create_in(index_dir, schema)4.2 定义Schema:文本、ID、日期、数值字段
4.2.1 Schema 设计原则
在设计 Schema 时,需要考虑:
- 存储需求:哪些字段需要直接读取?
- 索引需求:哪些字段需要参与搜索?
- 唯一性:哪些字段需要唯一约束?
- 性能影响:存储和索引的字段数量会影响性能
4.2.2 常用 Schema 定义
示例1:简单文章索引
from whoosh.fields import Schema, TEXT, ID
schema = Schema(
title=TEXT(stored=True), # 标题:存储+索引
content=TEXT(stored=False), # 内容:仅索引
path=ID(stored=True, unique=True) # 路径:唯一标识
)示例2:商品搜索索引
from whoosh.fields import Schema, TEXT, ID, NUMERIC, KEYWORD
schema = Schema(
name=TEXT(stored=True), # 商品名称
description=TEXT(stored=False), # 商品描述
sku=ID(stored=True, unique=True), # 商品SKU
price=NUMERIC(stored=True, numtype=float), # 价格
category=KEYWORD(stored=True) # 分类
)示例3:日志文件索引
from whoosh.fields import Schema, TEXT, ID, NUMERIC
schema = Schema(
timestamp=NUMERIC(stored=True, numtype=int), # 时间戳
level=KEYWORD(stored=True), # 日志级别
message=TEXT(stored=True), # 日志内容
file_path=ID(stored=True, unique=True) # 文件路径
)4.2.3 字段类型选择指南
| 字段类型 | 适用场景 | 是否分词 | 是否存储 | 常用参数 |
|---|---|---|---|---|
| TEXT | 全文搜索内容 | 是 | 可选 | stored, analyzer |
| ID | 唯一标识 | 否 | 通常存储 | stored, unique |
| KEYWORD | 标签、分类 | 否 | 可选 | stored, commas |
| NUMERIC | 价格、数量、时间戳 | 否 | 可选 | stored, numtype, sortable |
4.3 向索引添加文档数据
4.3.1 获取 Writer 对象
添加文档需要先获取 Writer 对象:
writer = ix.writer()4.3.2 添加单个文档
writer.add_document(
title="Python 编程入门",
content="这是一本关于 Python 的入门教程",
path="/docs/python.txt"
)4.3.3 批量添加文档
批量添加可以提高性能:
documents = [
{"title": "文档1", "content": "内容1", "path": "/doc1.txt"},
{"title": "文档2", "content": "内容2", "path": "/doc2.txt"},
{"title": "文档3", "content": "内容3", "path": "/doc3.txt"},
]
for doc in documents:
writer.add_document(**doc)4.3.4 提交与回滚
提交更改:
writer.commit() # 保存所有更改取消更改:
writer.cancel() # 回滚,不保存4.3.5 字符串编码注意事项
在 Python 3 中,确保使用 Unicode 字符串:
# ✅ 正确
writer.add_document(title=u"中文标题", content=u"中文内容")
# ❌ 错误(如果文件不是 UTF-8 编码)
with open("file.txt") as f:
content = f.read() # 可能不是 Unicode
writer.add_document(content=content)正确处理文件编码:
with open("file.txt", "r", encoding="utf-8") as f:
content = f.read()
writer.add_document(content=content)4.4 保存与打开索引文件
4.4.1 索引文件结构
创建索引后,会在指定目录生成多个文件:
my_index/
├─ _0.toc # 段目录信息
├─ _0.terms # 词项字典
├─ _0.postings # 倒排列表
├─ _0.stored # 存储字段
├─ _0.fieldlengths # 字段长度
└─ _0.lock # 写锁(临时文件)4.4.2 索引的持久化
调用 writer.commit() 后,索引会被持久化到磁盘:
writer = ix.writer()
writer.add_document(...)
writer.commit() # 此时刻索引被保存到磁盘4.4.3 打开已有索引
from whoosh.index import open_dir
# 打开索引
ix = open_dir("my_index")
# 使用搜索器
with ix.searcher() as searcher:
results = searcher.search(query)4.4.4 索引版本与段
Whoosh 使用段(Segments)管理索引:
- 段(Segment):索引的不可变单元
- 合并(Merging):定期合并多个段优化性能
查看段信息:
ix = open_dir("my_index")
print("段数量:", ix.doc_count())
print("文档数量:", ix.doc_count_all())4.4.5 索引锁定
当有 Writer 操作时,索引会被锁定:
# 检查是否被锁定
from whoosh.index import open_dir
try:
ix = open_dir("my_index")
writer = ix.writer()
except Exception as e:
print(f"索引可能被锁定: {e}")4.5 实战示例
4.5.1 完整示例:创建简单的文档索引
from whoosh.index import create_in, exists_in, open_dir
from whoosh.fields import Schema, TEXT, ID
import os
# 1. 准备目录
index_dir = "document_index"
if not os.path.exists(index_dir):
os.makedirs(index_dir)
# 2. 定义 Schema
schema = Schema(
title=TEXT(stored=True),
content=TEXT(stored=False),
path=ID(stored=True, unique=True)
)
# 3. 创建或打开索引
if exists_in(index_dir):
ix = open_dir(index_dir)
else:
ix = create_in(index_dir, schema)
# 4. 添加文档
writer = ix.writer()
writer.add_document(
title="Whoosh 快速入门",
content="Whoosh 是一个纯 Python 实现的全文检索库",
path="/docs/whoosh.txt"
)
writer.add_document(
title="Python 基础教程",
content="Python 是一门简洁而强大的编程语言",
path="/docs/python.txt"
)
writer.commit()
print("索引创建完成!")4.5.2 实战练习
练习1:创建一个包含日期字段的索引
- 添加
created字段(DATETIME 类型) - 为每篇文档添加创建时间
练习2:批量导入多个文件
- 读取一个文件夹下的所有
.txt文件 - 将每个文件的内容添加到索引
练习3:检查索引文件
- 查看生成的索引目录结构
- 打印出每个文件的大小
本章小结
本章我们学习了:
- 索引创建流程:从定义 Schema 到提交索引的完整步骤
- Schema 设计:如何根据业务需求定义字段类型
- 文档添加:单个和批量添加文档的方法
- 索引持久化:索引文件的保存、打开和管理
通过本章的学习,你应该能够独立创建一个完整的 Whoosh 索引,为后续的查询操作打下基础。
在下一章中,我们将学习如何执行基本的检索操作,包括各种查询类型和查询解析器的使用。