Py学习  »  Django

使用django和postgres进行全文检索

Python程序员 • 4 年前 • 322 次点击  

这些天我需要一个全文检索。这个方面的佼佼者是Elastic Search和Sorl:它们快速、灵活、资源消耗量大,而且需要java,而我创建的这个小项目几乎所有东西就运行在一个5美元的DigitalOcean droplet中。


在放弃了这些选项之后,我只剩下了Xapian和postgres全文检索,虽然Xapian的功能似乎更丰富,但我决定从postgres开始,因为它与django进行了原生集成,并且我对这个特定项目的要求也不高。


项目及需求


你可能已经注意到了,我在运营一个招聘网站。Voorjob基本上是从lever.co聚合职位并让用户通过它进行搜索。目前我的数据库中有大约25000个职位,这个数字增长的很缓慢,每增加2或3个职位,就会有另一个职位被关闭。所以,是的,如果我在这个数据库上采用了弹性搜索路径,那它将会是一个教科书般的过度设计情景。


实现


由于9.4版本的postgres增加了一些允许全文检索的特性。不久之后,Django就在其postgres特定特性中支持了这些特性。


要开始使用这个新特性,首先我需要在我的模型中增加一个SearchVectorField,还需要一些方法来使用向量化的职位描述更新这个字段:



这种方法对于某些很少更新的东西很适用,比如一个招聘网站,但如果你的应用程序经常更新,你应该避免这种策略,并使用一些能周期性地填充该向量的任务:



或者更好的是,通过阅读这个文档,你可以直接使用一个postgres触发器来完成。


职位查询


既然你已经准备好了你的数据库,是时候查询它了,我们来看看voorjob搜索视图的说教版本:



我在这里主要考虑两种查询:单词出现和“精确表达式”。是的,这种逻辑有一些缺陷,去起诉我吧:D


这个视图还有很多地方需要改进,django支持加权查询:


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


这个查询系统也更加灵活,它允许逻辑操作OR/AND和NOT。在不久的将来,我将改进我的招聘网站的搜索,并更新本文来描述其中的变化。


性能


在开发过程中,我使用了一个带有16GB内存和一个不错的NVMe固态硬盘的I5。在我的本地机器上对25000个职位运行查询基本上是瞬间完成的。


当我把这个项目投入生产时(在那个5美元的droplet中),事情变得越来越慢。


运行时间基准测试,我得到以下结果:


  • 在/路径下检索"django rest framework"  ( 扫描5000个条目花费1秒钟 )

  • 在/full路径下检索"django rest framework"  (扫描25000个条目花费3秒种 )


虽然性能不是最佳,但至少现在还可以。本文将继续进行更新,以展示任何性能改进。


考虑到我的检索需求不太大——总单词数不超过本文的25000个条目——使用postgres作为我的全文检索后端对这个早期阶段的MVP来说刚刚好。现在,我更感兴趣的是尝试一些新东西并增加这个网站的观众,而不是给予我的20个日常用户世界上最快的体验。


更新 (2020年2月9日)


好消息!我得知我可以向我的SearchVectorField添加一个索引:



现在各种情形的检索时间都降到了1秒钟。由于我的数据很小,所以这个索引使用的内存可以忽略不计。


英文原文:http://voorloopnul.com/blog/full-text-search-with-django-and-postgres/ 
译者:忧郁的红秋裤

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/54993
 
322 次点击