Django添加全文检索功能

2022-11-15 21:20:03 浏览数 (1)

全文检索不同于特定字段的模糊查询,使用全文检索的效率更高,并且能够对于中文进行分词处理。全文检索引擎是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户。这个过程类似于通过字典中的检索字表查字的过程。

haystack是django的开源搜索框架,该框架支持Solr、 Elasticsearch、 Whoosh、Xapian搜索引擎,其中whoosh是纯python编写的全文检索引擎,在实际操作过程中可以结合jieba中文分词对中文进行分词操作,达到对中文全文检索的不错效果。

haystack官方网站 whoosh文档

1.安装包

在Django虚拟环境中安装django-haystack和whoosh包

代码语言:javascript复制
pip install django-haystack==2.5.0
pip install whoosh

2.安装配置

在项目的settings.py的INSTALLED_APPS中加入haystack

代码语言:javascript复制
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'haystack',         # 全文检索框架
    ...,
)

在settings.py最后加入haystack配置

代码语言:javascript复制
# 全文检索框架配置
HAYSTACK_CONNECTIONS = {
    'default': {
        # 使用whoosh引擎
        'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
        # 索引文件路径
        'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
    }
}
# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

3.生成索引文件

在应用目录下创建search_indexes.py文件,在其中定义一个模型类对应的模型索引类

代码语言:javascript复制
from haystack import indexes
from goods.models import GoodsInfo

# 创建模型类对应的模型索引类
class GoodsInfoIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)

    def get_model(self):
        return GoodsInfo

    def index_queryset(self, using=None):
        return self.get_model().objects.all()

在templates目录下创建search/indexes/目录,再在创建的indexes目录下创建一个与应用同名的目录,比如search/indexes/goods/,最后在templates/search/indexes/goods/目录下创建goodsinfo_text.txt(命名:模型类名全小写_text.txt),在其中指定索引的属性

代码语言:javascript复制
# 指定索引的属性
{{ object.name }}
{{ object.desc }}

用以下命令生成索引文件

代码语言:javascript复制
python manage.py rebuild_index

4.使用全文检索

在项目的settings.py中加入haystack的url配置

代码语言:javascript复制
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^search', include('haystack.urls')),                        # 全文检索
    ...,
]

设置html表单

代码语言:javascript复制
<div class="search_con fl">
    {# get方式提交且action设置为/search #}
    <form method="get" action="/search">
        {# name设置为q #}
        <input type="text" class="input_text fl" name="q" placeholder="搜索商品">
        <input type="button" class="input_btn fr" name="" value="搜索">
    </form>
</div>

在templates/search/目录下创建search.html文件作为搜索结果的模板文件。搜索出结果后,haystack会把相应的上下文传递给模板文件,传递的上下文中模板变量包括如下:

  • query: 搜素关键字
  • page: 当前页的page对象,遍历page对象获得的是SearchResult对象,该对象的object属性就是模型类对象
  • paginator: 分页
  • query: paginator对象

注:通过在项目的settings.py中加入HAYSTACK_SEARCH_RESULTS_PER_PAGE=5可以控制每页显示数量

5.结合jieba分词对中文检索

安装jieba分词包

代码语言:javascript复制
pip install jieba

进入虚拟环境目录下的.virtualenvs/django/lib/python3.6/site-packages/haystack/backends创建ChineseAnalyzer.py文件,内容如下

代码语言:javascript复制
import jieba
from whoosh.analysis import Tokenizer, Token

class ChineseTokenizer(Tokenizer):
    def __call__(self, value, positions=False, chars=False,
            keeporiginal=False, removestops=True,
            start_pos=0, start_char=0, mode='', **kwargs):
        t = Token(positions, chars, removestops=removestops, mode=mode, **kwargs)
        seglist = jieba.cut(value, cut_all=True)
        for w in seglist:
            t.original = t.text = w 
            t.boost = 1.0 
            if positions:
                t.pos = start_pos   value.find(w)
            if chars:
                t.startchar = start_char   value.find(w)
                t.endchar = start_char   value.find(w)   len(w)
            yield t

def ChineseAnalyzer():
    return ChineseTokenizer()

复制一份whoosh_backend.py文件为whoosh_cn_backend.py

代码语言:javascript复制
cp whoosh_backend.py whoosh_cn_backend.py

打开whoosh_cn_backend.py文件,引入ChineseAnalyzer类from .ChineseAnalyzer import ChineseAnalyzer,并将analyzer=StemmingAnalyzer()改为analyzer=ChineseAnalyzer()

在项目的settings.py文件中修改配置

代码语言:javascript复制
HAYSTACK_CONNECTIONS = {
    'default': {
        # 使用whoosh引擎
        #'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
        # 将上面一句修改为下面
        'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine',
        # 索引文件路径
        'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
    }
}

最后重新生成索引文件即可

代码语言:javascript复制
python manage.py rebuild_index

本文作者: Ifan Tsai  (菜菜)

本文链接: https://cloud.tencent.com/developer/article/2164582

版权声明: 本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!

0 人点赞