如何使用Sphinx的BuildExcerpts
我设置了一个Sphinx的配置文件。我的数据结构非常简单,只有两个字段,一个是标题(title),另一个是正文(body)。标题是小说的名字,正文就是整本小说。为了简单起见,我只添加了一本小说。索引器工作得很好,使用Python的API查询Sphinx也非常简单。我对目前的进展感到很满意,这似乎是我调查过的最容易设置的全文搜索引擎(比Lucene或Solr简单得多,而且比Woosh快)。
我没有使用任何数据库后端。我把我的小说保存在普通的.txt文件中,并通过这个简单的xml(通过xmlpipe)添加了一个示例。
<?xml version="1.0" encoding="utf-8"?>
<sphinx:docset>
<sphinx:document id="1">
<title><![CDATA[Dan Simmons - I Canti di Hyperion 3 - Endymion]]></title>
<body><![CDATA[ * ALL THE NOVEL HERE * ]]></body>
</sphinx:document>
</sphinx:docset>
顺便说一下,我在档案中搜索了“tartaruga”,这是意大利语的“乌龟”,我确定这个词在文件中。实际上,它出现了三次,我想这就是Sphinx返回给我的结果('hits': 3
)。这是完整的结果:
{'attrs': [],
'error': '',
'fields': ['title', 'body'],
'matches': [{'attrs': {}, 'id': 1, 'weight': 1}],
'status': 0,
'time': '0.392',
'total': 1,
'total_found': 1,
'warning': '',
'words': [{'docs': 1, 'hits': 3, 'word': 'tartaruga'}]}
我最终想要的结果是这样的:
[
{
'title': 'Dan Simmons - I Canti di Hyperion 3 - Endymion',
'body': 'il vecchio mostrò quel suo sorriso a becco di tartaruga. — non bisogna dimenticare il palazzo dello shrike, né il nostro vecchio amico shrike, giusto? non ce ne sono altre?'
},
{
'title': 'Dan Simmons - I Canti di Hyperion 3 - Endymion',
'body': '— vieni più vicino, raul endymion. — la voce pareva il rumore di una lama spuntata che sfregasse su pergamena. le labbra si muovevano come il becco d\'una tartaruga.'
},
{
'title': 'Dan Simmons - I Canti di Hyperion 3 - Endymion',
'body': 'il becco di tartaruga ebbe una contrazione, la grossa testa si mosse in un cenno d\'assenso. notai ora che il viso del vecchio, malgrado i danni provocati dai secoli, aveva ancora tratti netti e spigolosi... un\'aria da satiro.'
},
]
我的意思是,想要一个包含出现次数的数组,里面有摘录来自哪本书,以及这个词在上下文中的位置(我选择了句子,但在匹配前后可以有n个词也可以)。我想我需要使用BuildExcerpts,但该怎么做呢?
另外,如果我想同时匹配“tartaruga”(乌龟)和“tartarughe”(乌龟的复数),我想发出一个像tartarug*
这样的查询。在Sphinx中该怎么做呢?谢谢!
1 个回答
我在做一个项目的时候也遇到过类似的情况。我建议,如果你只打算处理一本书,那把整本书作为一个字段加载并不是个好主意;如果你要处理很多书,那就更不合适了。以下是我处理的方式。
- 把书的内容分成一页一页存储在MySQL数据库里。
- 用Sphinx这个工具在数据库中搜索几百万页的文本——速度非常快,可以返回你想找的每一页(或者根据数据库中的页数,只返回前30页或其他数量)。
- 使用摘录生成器从某一页提取内容,并高亮显示搜索的关键词。
- 如果Python无法使用摘录生成器(可能只有PHP可以用),你也可以用正则表达式来完成同样的工作——只需要找到你的搜索词,然后用正则表达式提取前后的一些文本,再用另一个正则表达式来添加高亮效果。
你可以写一个Python脚本(我用的是从bash命令行运行的PHP脚本)来逐页提取文本,清理内容,然后把它添加到数据库中。
你需要一个至少有两个表的数据库,类似于:
books (字段可以叫 id, name, author)
pages (字段可以是 id, book_id, page_text)
Sphinx会返回一个页面的ID,然后你可以用简单的查询从MySQL中获取这页内容……
SELECT page_text FROM pages WHERE id = $idreturnedbysphinx;
然后把返回的文本发送给文本摘录器/高亮器。
Sphinx可以搜索精确的单词或词根(还有很多其他功能),但你需要在sphinx.conf文件中进行设置。
你至少需要两个索引定义:
indexer indexname1
{
#source database connection and sql query
source = src1
path = /var/data/indexname1
[... other settings ...]
#make sure stemming is switched off
morphology = none
}
#child index inherits the above, and add stemming
index indexname1stemmed : indexname1
{
path = /var/data/indexname1stemmed
morphology = stem_en
index_exact_words = 1
}
然后你还需要在Sphinx搜索中指定你想使用的匹配模式。我不太清楚Python的语法,但Sphinx的手册写得比我更清楚:
http://sphinxsearch.com/docs/current.html#matching-modes
你可以不使用SQL数据库,而是把内容保存在文本文件中,但我建议每页一个文本文件,这样更容易管理,否则你又会回到把整本电子书作为搜索结果的情况。