|
经过两个月的时间,毕设终于算是把所有主要功能都完成了,最近这一周为了实现全文检索的功能,也算
是查阅了不少资料,今天就在这里记录一下,以免以后再用到时抓瞎了~
首先介绍一下我使用的Django全文检索逻辑了,在网上查看了各种资料发现,Django上一般用到的检索
引擎基本上就是whoosh,sphinx,xapian了。后面的sphinx,xapian大家都可以在百度百科上找到相应的词条,
基本都是使用了很大的项目使用的,毕竟是基于C写的,效率上肯定不必多言了,但是我这个杀鸡的活还用不
到这两把牛刀了,这次我使用的是第一个whoosh引擎了,为什么使用这个呢?
因为whoosh是一个纯python实现的全文搜索组件。
主要特性
敏捷的API(Pythonic API)。
纯python实现,无二进制包。程序不会莫名其妙的崩溃。
按字段进行索引。
索引和搜索都非常的快 -- 是目前最快的纯python全文搜索引擎。
良好的构架,评分模块/分词模块/存储模块等各个模块都是可插拔的。
功能强大的查询语言(通过pyparsing实现功能)。
纯python实现的拼写检查(目前唯一的纯python拼写检查实现)
其实对我来说最重要的还是源于它的易用性和简单,毕竟对于毕业设计来说,需要的时间复杂度还是很
重要的"ㄟ( ▔, ▔ )ㄏ"
那么接下来就是分词了~如果把用户输入的内容全部拿去检索那不就和数据库的模糊查询一个意思了嘛~
所以我需要一个能分词的工具,但是whoosh的内部是使用正则来分词的,虽然这在英文的世界里理所应当,
但是毕竟我主要是用来检索中文的,所以必须要有一个靠得住的中文分词库,而中文分词要达到智能、准确
并不是一件容易的事,目前国内有不少商业的分词库。当然了,也有一些免费的中文分词库可以使用,比如
我使用的这个“jieba”分词库,而且他们号称是“做最好的 Python 中文分词组件”,这是他们的GitHub地址。
好了,现在检索引擎和分词库都有了,那么接下来就是如何将这两个整合到我们的项目中了~下面出场
的就是今天的主角了~django-haystack,这个一款同时支持whoosh,solr,Xapian,Elasticsearc四种全文检索引
擎的第三方app,这意味着如果你不想使用whoosh,那你随时可以将之更换成Xapian等其他搜索引擎,而不
用更改代码。正如Django一样,Django-haystack的使用也非常简单。
现在我们该把他们整合到一起了,首先,先把他们都安装上吧
- pip install whoosh
- pip install jieba
- pip install django-haystack
- 然后我们在app目录下建立一个search_indexes.py,代码如下:
- 复制代码
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- # [url=home.php?mod=space&uid=315144]@date[/url] : 2015-05-07 14:15:13
- # [url=home.php?mod=space&uid=267564]@Author[/url] : jonnyF (fuhuixiang@jonnyf.com)
- # @Link : http://jonnyf.com
- from dlnubuy.models import Product
- from haystack import indexes
- class ProductIndex(indexes.SearchIndex, indexes.Indexable):
- text = indexes.CharField(document=True, use_template=True)
- # 对pdname和description字段进行索引
- pdname = indexes.CharField(model_attr='pdname')
- description = indexes.CharField(model_attr='description')
- def get_model(self):
- return Product
- def index_queryset(self, using=None):
- return self.get_model().objects.all()
复制代码
复制代码
这里要注意的是文件名称必须是search_indexes.py,否则会报错的!!!
然后在模板目录下面建立templates/search/indexes/<appname>/product_text.txt,这个模板的作用是让text字
段包含的内容,在后面的模板中可能会有用。
然后在settings.py里面配置:
复制代码
- # full text search
- HAYSTACK_CONNECTIONS = {
- 'default': {
- 'ENGINE': 'dlnubuy.whoosh_cn_backend.WhooshEngine',
- 'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
- },
- }
复制代码
# 自动更新索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
复制代码
这样我们的检索引擎,分词器都连在一起了,但是要主要的一点是,我们现在的检索引擎依旧使用的是自
身的分词器,而不是我们的jieba,所以接下来就是把他俩和在一起了,要注意的是我这里以及对whoosh的检
索引擎修改过了,所以为了方便移植,所以我将whoosh的检索引擎放在了我app的目录下面,这样就不再依
赖本机的环境了。
首先先将../Python27/Lib/site-packages/haystack/backends目录中的whoosh_backend.py文件复制到app
目录下并改名为whoosh_cn_backend.py,这个文件名要和setting文件中配置中的一样,当然,我们不是全部
都修改这个文件,修改的仅仅是期中的个别位置,修改的地方如下:
复制代码
#在全局引入的最后一行加入jieba分词器
from jieba.analyse import ChineseAnalyzer
#修改
schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(),
field_boost=field_class.boost, sortable=True)
复制代码
之后是重建索引:python manage.py rebuild_index 这样修改完成之后就可以使用了,关于自动更新索引这
件事来说,我觉得并没有必要在每次修改数据库的时候都更新,所以后来改为了只有修改我检索的字段的时
候才使用manage.py update_index 更新索引。
接下来就是在搜索框提交之后来处理的后台逻辑了:
复制代码
# 全局搜索
def full_search(request):
sform = SearchForm(request.GET)
posts = sform.search()
template = 'product_search_list.html'
c = Context({'posts': posts})
return render_to_response(template, c)
复制代码
由于我使用的是模板来渲染的显示页面,所以在这个我就不贴出代码来了(太简单了,没什么要注意的),
主要就是在模板中使用循环来遍历posts变量,而这个变量的类型是SearchResult的,这里就简单的列举一
下SearchResult的一些参数了:
复制代码
Attribute Reference
The class exposes the following useful attributes/properties:
app_label - The application the model is attached to.
model_name - The model’s name.
pk - The primary key of the model.
score - The score provided by the search engine.
object - The actual model instance (lazy loaded).
model - The model class.
verbose_name - A prettier version of the model’s class name for display.
verbose_name_plural - A prettier version of the model’s plural class name for display.
searchindex - Returns the SearchIndex class associated with this result.
distance - On geo-spatial queries, this returns a Distance object representing the distance the result was fro
m the focused point.
复制代码
这里我使用的是object,然后通过{{i.object.description}}这样的模板来显示细节的,其他的地方就是具体
项目具体细节咯~
|
|