Django本身并没有提供全文搜索的功能,而自己给Django添加全文搜索的功能选择也有很多,可以用Sphinx,Lucene,Xapian等等来做。这里我们选用基于Lucene的全文搜索服务器Solr来快速的搭建Django的全文搜索应用。
需要用到的开源项目:
Solr:http://lucene.apache.org/solr/ (Apache License)
Django-solr-search: http://code.google.com/p/django-solr-search/( BSD L)
Pymmseg-cpp: http://code.google.com/p/pymmseg-cpp/ (MIT L)
Django-solr-search是用来连接Solr服务器的Django插件,Py mmseg-cpp是Python封装的mmseg中文分词模块。
1.配置环境
首先安装Solr, 下载下来直接解压,然后进入apache-solr-1.4.0/example下面,直接运行:
java -jar start.jar
然后查看http://localhost:8983/solr/,看到欢迎界面,一切ok。
然后把Django-solr-search下载下来,可以选择直接setup,也可以直接把其中 的solango放入需要增加全文搜索的Project下面。
然后修改settings.py,加入solango的app,如下:
INSTALLED_APPS = { |
添加Solr的路径:
SOLR_ROOT ='path/apache-solr-1.4.0/example/' |
最后在项目下运行命令:
让django启动Solr服务器 python manage.py solr --start
查看是否连接成功:
python manage.py shell
>>> import solango |
显示True,环境就搭好了。
2.定义Document模型
先看我们需要全文搜索的model:
class ElectronicComponent(models.Model): |
根据上面的model,定义全文搜索的Document模型:
from models import ElectronicComponent |
根据原有的ElectronicComponent生成ElectronicComponentDocument全文搜索模型,后面transform_user函数返回自己想给user返回的值。
3.建立索引
定义好以上的模型后,就可以建立索引了,先查看一下刚才定义的fields:
运行命令:python manage.py solr --fields
########## FIELDS ###########
<field name="mfg" type="string" indexed="true" stored="true" omitNorms="false" required="false" multiValued="false"/> <field name="url" type="string" indexed="true" stored="true" omitNorms="false" required="false" multiValued="false"/> <field name="text" type="text" indexed="true" stored="true" omitNorms="false" required="false" multiValued="true"/> <field name="site_id" type="integer" indexed="true" stored="true" omitNorms="false" required="true" multiValued="false"/> <field name="desp" type="string" indexed="true" stored="true" omitNorms="false" required="false" multiValued="false"/> <field name="partno" type="string" indexed="true" stored="true" omitNorms="false" required="false" multiValued="false"/> <field name="cate_ID" type="string" indexed="true" stored="true" omitNorms="false" required="false" multiValued="false"/> <field name="user" type="string" indexed="true" stored="true" omitNorms="false" required="false" multiValued="false"/> <field name="model" type="string" indexed="true" stored="true" omitNorms="false" required="true" multiValued="false"/> <field name="p_name" type="string" indexed="true" stored="true" omitNorms="false" required="false" multiValued="false"/> <field name="id" type="string" indexed="true" stored="true" omitNorms="false" required="true" multiValued="false"/> <field name="pack" type="string" indexed="true" stored="true" omitNorms="false" required="false" multiValued="false"/>
######## COPY FIELDS ########
<copyField source="mfg" dest="text"/> <copyField source="desp" dest="text"/> <copyField source="partno" dest="text"/> <copyField source="cate_ID" dest="text"/> <copyField source="user" dest="text"/> <copyField source="p_name" dest="text"/> <copyField source="pack" dest="text"/>
|
以上就是刚才模型中定义的Fields,如果以前已经有旧的索引存在了,就先运行:
python manage.py solr –-flush
把旧索引清空。然后根据我们定义的Document模型同步Schema.xml:
python manage.py solr --schema
最后重新启动Solr就可建立索引:
python manage.py solr --reindex
4.查询与分词
能够简便的实现facets查询,这也是选择Solr来做全文搜索服务器原因之一。
对刚才建立的索引,做一个测试:
In [1]: from solango import connection
|
上面给facet增加一个新的field:cate_ID(分类 ),以“ad”作为关键字来查询,可以看到共检索出25条数据,同时也得到了这些数据位于5种不同分类及分别的数量。
利用facet进行查询,对于分类搜索提供了一个行之有效的解决方案。
定义更多种类的Query来实现搜索,基本上就跟Django没有关系,完全看对Solr的操作了。
至于分词,可以独立出来看,而且可以选择的方式方法很多,这里拿Pymmseg举个例子:
>>> from pymmseg import mmseg |
5.模板显示与排序
对于模板的显示,Django-solr-search也提供了简洁的方式,在定义Document模型的之后加入对应的模板,来看个官方的例子。
在定义模型的时候指定Document对应的模板:
class EntryDocument(solango.SearchDocument):
|
模板:
<div class="searchdocument"> |
在其他的页面中使用render_html方法, 引用嵌入定义的Document模板
{% for doc in paginator.results.documents %} |
当然,你也可以像以前一样使用普通的方式渲染模板。
后台代码:
def solr_search(request): |
模板中引用:
{% for cate_ID in cate_ID_dict %} |
显示效果:
排序其实都是通过Solr来控制的,在settings.py中加入下面代码来控制排序:
SEARCH_SORT_PARAMS = { |
6.索引的更新
索引的更新问题对于一个应用来说也至关重要。这里提供了两种基本的更新方法。
ImmediateIndexer:
这个是默认的即时更新,不需要任何设置。但是lucene的索引创建速度并不快,因此这种方法只适合在数据量比较小,数据写入和删除操作并不多的情况下使用。
DBQueuedIndexer
这个方法是通过在数据库中创建一张表,记录下来数据操作的队列,然后在指定的时间针对这个队列表里的数据进行更新操作。
需要在settings.py加入:
SEARCH_INDEXER = "solango.indexing.DBQueuedIndexer" |
定时运行:
python manage.py solr –index-queued
回过头来再看一下Django使用Solr搜索的原理,并不复杂,就是一个完整的爬虫类:
通过 urllib2对Solr服务器的url进行访问,再读取Solr返回的xml文本,对文本解析,封装,最后渲染模板。
以上就是快速的给Django应用加入全文搜索的一个方法,主要还是Django-solr-search的使用。而这个插件应用背景也比较有趣,最初做给是给《华盛顿时报》的网站使用的,这家报纸从创建之初竟然连续20年从未实现过盈利。
官方文档地址:http://www.screeley.com/djangosolr/index.html
除了 Django-solr-search之外,还有很多第三方的全文搜索插件可以使用,例如Haystack 等等,有兴趣也不妨学习一下。