使用Django和Postgres进行全文搜索的实例代码

这些天,我需要全文搜索。这个区块中最酷的孩子们是Elastic Search和Sorl:他们快速,灵活,资源消耗沉重并且需要Java,这几乎是我想要的一个5美元的数字海洋飞车上运行的宠物项目所需的所有东西。

放弃这些选项后,我剩下了Xapian和postgres全文搜索的功能,而xapian似乎功能更丰富,我决定从postgres开始,因为它与django进行了本机集成,并且对这个特定项目的要求不高。

项目及其要求

您可能已经注意到,我正在运行工作板。 Voorjob基本上是从lever.co聚合工作,并让用户搜索它。目前,我在数据库中大约有25,000个工作,这个数字增长缓慢,每增加2或3个工作,就会关闭另一个工作。是的,如果我采用了弹性搜索路径,那将是一本教科书过度设计的情况。

实施

从9.4版开始,postgres添加了一些允许全文本搜索的功能。不久之后,Django在postgres特定功能中镜像了这些功能。

要开始使用此新功能,我基本上需要在模型中使用SearchVectorField,并需要使用矢量化的职位描述来更新此字段的方法:

from django.contrib.postgres.search import SearchVectorField, SearchVector
class Job(models.Model):
  title = models.CharField(max_length=200, blank=True)
  location = models.CharField(max_length=50, blank=True)
  body = models.TextField(null=True)
  body_vector = SearchVectorField(null=True)

  def make_search_vector():
    self.body_vector=SearchVector('body')

  def save(self, *args, **kwargs):
    self.make_search_vector()
    super(Model, self).save(*args, **kwargs)

这种方法适用于很少更新的工作,例如工作板,但是如果您的应用程序经常更新,则应避免使用此策略,并应定期执行一些任务来填充向量:

Job.objects.all().update(body_vector=SearchVector('body'))

甚至更好的是,您可以通过阅读本文档,使用postgres触发器直接进行操作。

查询工作

现在您已经准备好数据库,现在可以查询它了,让我们看一下voorjob搜索视图的教学版本:

from django.contrib.postgres.search import SearchQuery

class Index(ListView):
  model = Job
  paginate_by = 30

  def get_queryset(self):
    search = self.request.GET.get("search", None)
    queryset = Job.objects.all()

    if search:
      if '"' in search:
        query = SearchQuery(search.replace('"', ''), search_type='phrase')
      else:
        query = SearchQuery(search)
      queryset = queryset.filter(body_vector=query)
    else:
      queryset = queryset

    return queryset

我基本上在这里考虑两种查询:单词存在和“精确表达式”。是的,该逻辑中存在一些缺陷,请继续起诉我:D

还有很多可以改进的地方,django支持加权查询:

vector = SearchVector('title',weight ='A')+ SearchVector('body',weight ='B')
Job.objects.all()。update(body_vector = vector)

这最终将以更好的顺序返回结果,其中标题中的匹配比正文中的匹配更重。

查询系统也更加灵活,允许进行逻辑运算OR / AND和NOT。在不久的将来,我将改善对工作板的搜索,并更新此帖子以描述所做的更改。

性能

在开发过程中,我使用了具有16GB内存和不错的NVMe的I5。对本地计算机中的25k作业运行查询基本上是瞬时的。

当我将项目转移到生产环境时(每滴5美元),事情变得越来越慢了。

运行密西西比基准测试,我得到以下结果:

在/ django rest framework上搜索((1个密西西比州以扫描5K条目))

在/ full /上搜索“ django rest framework”(-3个密西西比州,扫描25K条目)

不是最好的性能,但现在可以使用。本文将进行更新以反映任何性能改进。

考虑到我的搜索需求不高-超过25k的条目,且字数过多的文章并不比本文大很多-使用postgres作为我的全文搜索的后端,对于此早期MVP来说效果很好。现在,我比每天给我20个用户提供最快的体验,对尝试事物和扩大董事会成员更感兴趣。

更新(2020年2月9日)

好消息! 我了解到可以将索引添加到SearchVectorField中:

from django.contrib.postgres.indexes import GinIndex

class Job(models.Model):
  class Meta:
    indexes = (GinIndex(fields=["body_vector"]),)
  title = models.CharField(max_length=200, blank=True)
  location = models.CharField(max_length=50, blank=True)
  body = models.TextField(null=True)
  body_vector = SearchVectorField(null=True)
  def make_search_vector():
    self.body_vector=SearchVector('body')
  def save(self, *args, **kwargs):
    self.make_search_vector()
    super(Model, self).save(*args, **kwargs)

现在,所有情况下的搜索时间均降至1个密西西比州。 由于我的数据很小,因此用于该索引的内存量可以忽略不计。

总结

以上所述是小编给大家介绍的使用Django和Postgres进行全文搜索的实例代码,希望对大家有所帮助!

(0)

相关推荐

  • Django项目之Elasticsearch搜索引擎的实例

    1.使用Docker安装Elasticsearch及其扩展 获取镜像,可以通过网络pull sudo docker image pull delron/elasticsearch-ik:2.4.6-1.0 或者加载镜像文件 sudo docker load -i elasticsearch-ik-2.4.6_docker.tar 修改elasticsearch的配置文件 elasticsearc-2.4.6/config/elasticsearch.yml第54行,更改ip地址为本机ip地址 n

  • Python中使用haystack实现django全文检索搜索引擎功能

    前言 django是python语言的一个web框架,功能强大.配合一些插件可为web网站很方便地添加搜索功能. 搜索引擎使用whoosh,是一个纯python实现的全文搜索引擎,小巧简单. 中文搜索需要进行中文分词,使用jieba. 直接在django项目中使用whoosh需要关注一些基础细节问题,而通过haystack这一搜索框架,可以方便地在django中直接添加搜索功能,无需关注索引建立.搜索解析等细节问题. haystack支持多种搜索引擎,不仅仅是whoosh,使用solr.elas

  • pycharm+django创建一个搜索网页实例代码

    本文主要研究的是pycharm+django创建一个搜索网页的实例代码,具体步骤和代码示例如下. 创建工程 比如,我创建的工程目录结构如下: 命令行 进入windows命令行,进入根目录: python manage.py startapp django_web 接着你会在pycharm中发现,多了一个django_web文件夹.如下将截图: 创建一个test.html <!DOCTYPE html> <html> <head> <title>开始搜索<

  • django使用haystack调用Elasticsearch实现索引搜索

    前言: 在做一个商城项目的时候,需要实现商品搜索功能. 说到搜索,第一时间想到的是数据库的 select * from tb_sku where name like %苹果手机% 或者django的 SKU.objects.filter(name__contains="苹果手机") 但是,假如你的数据库有几千万条数据,name字段没有索引,可能查询需要十几分钟,用户可能会等你?那为什么不给name字段增加索引?商品表不仅仅是用来查询,也会经常修改数据,新增删除数据等.建立索引后,做增删

  • 使用Django和Postgres进行全文搜索的实例代码

    这些天,我需要全文搜索.这个区块中最酷的孩子们是Elastic Search和Sorl:他们快速,灵活,资源消耗沉重并且需要Java,这几乎是我想要的一个5美元的数字海洋飞车上运行的宠物项目所需的所有东西. 放弃这些选项后,我剩下了Xapian和postgres全文搜索的功能,而xapian似乎功能更丰富,我决定从postgres开始,因为它与django进行了本机集成,并且对这个特定项目的要求不高. 项目及其要求 您可能已经注意到,我正在运行工作板. Voorjob基本上是从lever.co聚

  • JavaScript切换搜索引擎的导航网页搜索框实例代码

    废话不多说了,直接给大家贴代码了,具体代码如下所述: <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <style> #search ul { list-style-type: none; display: block; width: 100px; height

  • Django中的cookie与session操作实例代码

    添加cookie: def login(req): if req.method=="POST": uf = UserInfoForm(req.POST) if uf.is_valid(): username = uf.cleaned_data["username"] password = uf.cleaned_data["password"] print username,password users = UserInfo.objects.fil

  • Android 百度地图POI搜索功能实例代码

    在没介绍正文之前先给大家说下poi是什么意思. 由于工作的关系,经常在文件中会看到POI这三个字母的缩写,但是一直对POI的概念和含义没有很详细的去研究其背后代表的意思.今天下班之前,又看到了POI这三个字母,决定认认真真的搜索一些POI具体的含义. POI是英文的缩写,原来的单词是point of interest, 直译成中文就是兴趣点的意思.兴趣点这个词最早来自于导航地图厂商.地图厂商为了提供尽可能多的位置信息,花费了很大的精力去寻找诸如加油站,餐馆,酒店,景点等目的地,这些目的地其实都可

  • Django+mysql配置与简单操作数据库实例代码

     第一步:下载mysql驱动 cmd进入创建好的django项目目录:使用命令 pip install mysqlclient 等待安装成功! 第二步:在settings.py中配置mysql连接参数(没有mysql的先装mysql) DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '数据库名(你得先在mysql中创建数据库)', 'USER':'mysql用户名(如root)', 'PASSWOR

  • django项目中使用手机号登录的实例代码

    本文使用聚合数据的短信接口,需要先获取到申请接口的appkey和模板id 项目目录下创建ubtils文件夹,定义返回随机验证码和调取短信接口的函数 function.py文件 import random import re # 随机数 def range_num(num): # 定义一个种子,从这里面随机拿出一个值,可以是字母 seeds = "1234567890" # 定义一个空列表,每次循环,将拿到的值,加入列表 random_num = [] # choice函数:每次从see

  • django 文件上传功能的相关实例代码(简单易懂)

    一.新建项目,在主配置文件中,修改以下内容: ALLOWED_HOSTS = ['127.0.0.1','localhost'] MEDIA_ROOT = os.path.join(BASE_DIR,'media') STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), MEDIA_ROOT] 在该项目下新建一个与 manage.py 同级的目录文件,目录名为media. 在media文件夹下新建一个子目录,作为上传文件的保存位置,这里我把

  • Django 博客实现简单的全文搜索的示例代码

    作者:HelloGitHub-追梦人物 文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 搜索是一个复杂的功能,但对于一些简单的搜索任务,我们可以使用 Django Model 层提供的一些内置方法来完成.现在我们来为我们的博客提供一个简单的搜索功能. 概述 博客文章通常包含标题和正文两个部分.当用户输入某个关键词进行搜索后,我们希望为用户显示标题和正文中含有被搜索关键词的全部文章.整个搜索的过程如下: 用户在搜素框中输入搜索关键词,假设为 "django",

  • python仿evething的文件搜索器实例代码

    今天看到everything搜索速度秒杀windows自带的文件管理器,所以特地模仿everything实现了文件搜索以及打开对应文件的功能,首先来一张搜索对比图. 这是evething搜索效果: 这是自己实现的效果: 主要功能就是python的os库的文件列表功能,sqllite创建表,插入数据以及模糊搜索,然后就是tkiner实现的界面功能.全部代码贴出来做一次记录,花费一天时间踩坑. # coding=utf-8 import tkinter as tk import tkinter.me

随机推荐