Django中使用Whoosh进行全文检索的方法


Posted in Python onMarch 31, 2019

Whoosh 是纯Python实现的全文搜索引擎,通过Whoosh可以很方便的给文档加上全文索引功能。

什么是全文检索

简单讲分为两块,一块是分词,一块是搜索。比如下面一段话:

上次舞蹈演出直接在上海路的弄堂里

比如我们现在想检索上次的演出,通常我们会直接搜索关键词: 上次演出 ,但是使用传统的SQL like 查询并不能命中上面的这段话,因为在 上次 和 演出 中间还有 舞蹈 。然而全文搜索却将上文切成一个个Token,类似:

上次/舞蹈/演出/直接/在/上海路/的/弄堂/里

切分成Token后做反向索引(inverted indexing),这样我们就可以通过关键字很快查询到了结果了。

解决分词问题

分词是个很有技术难度的活,比如上面的语句中一个难点就是到底是 上海路 还是 上海 呢?Python有个中文分词库: 结巴分词 ,我们可以通过结巴分词来完成索引中分词工作,结巴分词提供了Whoosh的组件可以直接集成,代码示例

遇到的问题

如果是在一些VPS上测试的时候非常慢的话可能是内存不足,比如512MB做一个博客索引非常慢,尝试升级到1GB后可以正常使用了。

代码

import logging
import os
import shutil
from django.conf import settings

from whoosh.fields import Schema, ID, TEXT, NUMERIC
from whoosh.index import create_in, open_dir
from whoosh.qparser import MultifieldParser
from jieba.analyse import ChineseAnalyzer

from .models import Article

log = logging.getLogger(__name__)

index_dir = os.path.join(settings.BASE_DIR, "whoosh_index")

indexer = open_dir(index_dir)


def articles_search(keyword):

  mp = MultifieldParser(
    ['content', 'title'], schema=indexer.schema, fieldboosts={'title': 5.0})
  query = mp.parse(keyword)

  with indexer.searcher() as searcher:
    results = searcher.search(query, limit=15)

    articles = []
    for hit in results:
      log.debug(hit)
      articles.append({
        'id': hit['id'],
        'slug': hit['slug'],
      })

  return articles


def rebuild():
  if os.path.exists(index_dir):
    shutil.rmtree(index_dir)
  os.makedirs(index_dir)

  analyzer = ChineseAnalyzer()
  schema = Schema(
    id=ID(stored=True, unique=True),
    slug=TEXT(stored=True),
    title=TEXT(),
    content=TEXT(analyzer=analyzer))
  indexer = create_in(index_dir, schema)

  __index_all_articles()


def __index_all_articles():
  writer = indexer.writer()
  published_articles = Article.objects.exclude(is_draft=True)
  for article in published_articles:
    writer.add_document(
      id=str(article.id),
      slug=article.slug,
      title=article.title,
      content=article.content,
    )
  writer.commit()


def article_update_index(article):
  '''
  updating an article to indexer, adding if not.
  '''
  writer = indexer.writer()
  writer.update_document(
    id=str(article.id),
    slug=article.slug,
    title=article.title,
    content=article.content,
  )

  writer.commit()


def article_delete_index(article):
  writer = indexer.writer()
  writer.delete_by_term('id', str(article.id))

  writer.commit()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python内置函数Type()函数一个有趣的用法
Feb 18 Python
Python实现Linux的find命令实例分享
Jun 04 Python
python添加模块搜索路径方法
Sep 11 Python
Python实现查看系统启动项功能示例
May 10 Python
Python使用jsonpath-rw模块处理Json对象操作示例
Jul 31 Python
Python二叉树的镜像转换实现方法示例
Mar 06 Python
详解Python_shutil模块
Mar 15 Python
网易有道2017内推编程题 洗牌(python)
Jun 19 Python
Python绘制堆叠柱状图的实例
Jul 09 Python
Tensorflow获取张量Tensor的具体维数实例
Jan 19 Python
详解python tkinter 图片插入问题
Sep 03 Python
python subprocess pipe 实时输出日志的操作
Dec 05 Python
Python实现的爬取小说爬虫功能示例
Mar 30 #Python
Python文件打开方式实例详解【a、a+、r+、w+区别】
Mar 30 #Python
Python函数装饰器常见使用方法实例详解
Mar 30 #Python
Python函数基础实例详解【函数嵌套,命名空间,函数对象,闭包函数等】
Mar 30 #Python
Python函数的参数常见分类与用法实例详解
Mar 30 #Python
Python实现定时执行任务的三种方式简单示例
Mar 30 #Python
详解Python解决抓取内容乱码问题(decode和encode解码)
Mar 29 #Python
You might like
ThinkPHP中pathinfo的访问模式、路径访问模式及URL重写总结
2014/08/23 PHP
PHP输入输出流学习笔记
2015/05/12 PHP
jquery+php实现导出datatables插件数据到excel的方法
2015/07/06 PHP
PHP实现求连续子数组最大和问题2种解决方法
2017/12/26 PHP
详解PHP中的外观模式facade pattern
2018/02/05 PHP
PHP使Laravel为JSON REST API返回自定义错误的问题
2018/10/16 PHP
js类中的公有变量和私有变量
2008/07/24 Javascript
JS自定义功能函数实现动态添加网址参数修改网址参数值
2013/08/02 Javascript
Jquery绑定事件(bind和live的区别介绍)
2013/08/23 Javascript
jquery判断浏览器后退时候弹出消息的方法
2014/08/11 Javascript
JavaScript中变量声明有var和没var的区别示例介绍
2014/09/15 Javascript
JavaScript中检查对象property的存在性方法介绍
2014/12/30 Javascript
jQuery中ajax的load()与post()方法实例详解
2016/01/05 Javascript
BootStrap智能表单实战系列(十一)级联下拉的支持
2016/06/13 Javascript
chrome下判断点击input上标签还是其余标签的实现方法
2016/09/18 Javascript
JavaScript实现动态增删表格的方法
2017/03/09 Javascript
jquery中封装函数传递当前元素的方法示例
2017/05/05 jQuery
ES6模块化的import和export用法方法总结
2017/08/08 Javascript
67 个节约开发时间的前端开发者的工具、库和资源
2017/09/12 Javascript
对VUE中的对象添加属性
2018/09/18 Javascript
如何在selenium中使用js实现定位
2020/08/18 Javascript
vscode+gulp轻松开发小程序的完整步骤
2020/10/18 Javascript
[07:09]DOTA2-DPC中国联赛 正赛 Ehome vs Elephant 选手采访
2021/03/11 DOTA
Python读取一个目录下所有目录和文件的方法
2016/07/15 Python
Django学习教程之静态文件的调用详解
2018/05/08 Python
python调用tcpdump抓包过滤的方法
2018/07/18 Python
浅谈python requests 的put, post 请求参数的问题
2019/01/02 Python
Python中一般处理中文的几种方法
2019/03/06 Python
Python3如何对urllib和urllib2进行重构
2019/11/25 Python
windows上彻底删除jupyter notebook的实现
2020/04/13 Python
jupyter notebook oepncv 显示一张图像的实现
2020/04/24 Python
Python super()函数使用及多重继承
2020/05/06 Python
如何基于python把文字图片写入word文档
2020/07/31 Python
超市商业计划书
2014/05/04 职场文书
有关爱国演讲稿
2014/05/07 职场文书
对Golang中的FORM相关字段理解
2021/05/02 Golang