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语言编写电脑时间自动同步小工具
Mar 08 Python
利用打码兔和超人打码自封装的打码类分享
Mar 16 Python
跟老齐学Python之私有函数和专有方法
Oct 24 Python
在Python的循环体中使用else语句的方法
Mar 30 Python
Python编程判断一个正整数是否为素数的方法
Apr 14 Python
解决python使用open打开文件中文乱码的问题
Dec 29 Python
Python聊天室程序(基础版)
Apr 01 Python
解决python读取几千万行的大表内存问题
Jun 26 Python
处理python中多线程与多进程中的数据共享问题
Jul 28 Python
pandas 对日期类型数据的处理方法详解
Aug 08 Python
Spark处理数据排序问题如何避免OOM
May 21 Python
Python fileinput模块如何逐行读取多个文件
Oct 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
PHP 超链接 抓取实现代码
2009/06/29 PHP
在项目中寻找代码的坏命名
2012/07/14 PHP
PHP实现格式化文件数据大小显示的方法
2015/01/03 PHP
php定义参数数量可变的函数用法实例
2015/03/16 PHP
php自动载入类用法实例分析
2016/06/24 PHP
PHP框架实现WebSocket在线聊天通讯系统
2019/11/21 PHP
javascript DOM编程实例(智播客学习)
2009/11/23 Javascript
JavaScript 更严格的相等 [译]
2012/09/20 Javascript
js实现单一html页面两套css切换代码
2013/04/11 Javascript
jQuery 复合选择器应用的几个例子
2014/09/11 Javascript
JS实现仿Windows经典风格的选项卡Tab切换代码
2015/10/20 Javascript
Vuejs第十二篇之动态组件全面解析
2016/09/09 Javascript
详解Angular Reactive Form 表单验证
2017/07/06 Javascript
解读vue生成的文件目录结构及说明
2017/11/27 Javascript
JavaScript设计模式之单例模式原理与用法实例分析
2018/07/26 Javascript
新年快乐! javascript实现超级炫酷的3D烟花特效
2019/01/30 Javascript
Vue的生命周期操作示例
2019/09/17 Javascript
js实现超级玛丽小游戏
2020/03/18 Javascript
[54:53]完美世界DOTA2联赛PWL S2 GXR vs PXG 第二场 11.18
2020/11/18 DOTA
Python创建二维数组实例(关于list的一个小坑)
2017/11/07 Python
Python3列表内置方法大全及示例代码小结
2019/05/10 Python
Python math库 ln(x)运算的实现及原理
2019/07/17 Python
python之PyQt按钮右键菜单功能的实现代码
2019/08/17 Python
Keras设置以及获取权重的实现
2020/06/19 Python
草莓巧克力:Shari’s Berries
2017/02/07 全球购物
主持人演讲稿范文
2013/12/28 职场文书
国际贸易求职信
2014/07/05 职场文书
上课迟到检讨书300字
2014/10/15 职场文书
故意伤害辩护词
2015/05/21 职场文书
2015年度对口支援工作总结
2015/07/22 职场文书
党风廉政承诺书2016
2016/03/25 职场文书
导游词之江南园林狮子林
2019/09/16 职场文书
总结一些Java常用的加密算法
2021/06/11 Java/Android
Nginx的基本概念和原理
2022/03/21 Servers
Mysql多层子查询示例代码(收藏夹案例)
2022/03/31 MySQL
MySQL数据库 任意ip连接方法
2022/05/20 MySQL