如何在 Django 的 sqlite3 数据库中使用全文搜索?

Sна*_*ƒаӽ 6 python sqlite django full-text-search

我正在使用 sqlite3 数据库开发 django 应用程序,该应用程序具有固定的数据库内容。固定我的意思是数据库的内容不会随着时间的推移而改变。该模型是这样的:

class QScript(models.Model):
    ch_no = models.IntegerField()
    v_no = models.IntegerField()
    v = models.TextField()
Run Code Online (Sandbox Code Playgroud)

表中有大约 6500 条记录。给定一个可能缺少某些单词或拼写错误的文本,我需要确定它的ch_nov_no。例如,如果vdb 中有一个字段,其中包含文本"This is an example verse",则给定的文本,如"This an egsample verse"应该给我ch_nov_nofrom db。我相信这可以使用全文搜索来完成。

我的查询是:

  1. 全文搜索可以做到这一点吗?根据我的研究,我猜测它可以,正如在sqlite3 页面中所说:全文搜索是“Google、Yahoo 和 Bing 对放置在万维网上的文档所做的事情”。在 SO 中引用,我也阅读了这篇文章以及许多其他文章,但没有找到任何与我的要求非常匹配的内容。

  2. 如何在 Django 模型中使用 FTS?我读了这个,但没有帮助。似乎太过时了。在此处阅读:“...需要直接操作数据库以添加全文索引”。搜索主要提供与 MySQL 相关的信息,但我需要在 sqlite3 中进行。那么如何在 sqlite3中进行直接操作呢?


编辑:

我选择坚持使用 sqlite3 是否正确?或者我应该使用不同的东西(比如Alex Morozov所说的 haystack+elasticsearch )?我的数据库不会变大,我研究过,对于小型数据库,sqlite几乎总是更好(我的情况与sqlite 何时使用 checklist中的第四个匹配)。

Col*_*Two 5

SQLite 的 FTS 引擎基于标记 - 搜索引擎尝试匹配的关键字。

有多种标记器可用,但它们相对简单。“简单”分词器只是将每个单词分开并将其小写:例如,在字符串“The Quick Brown Fox Jumps Over the Lazy Dog”中,单词“Jumps”会匹配,但不会匹配“Jump”。“porter”分词器更先进一些,它剥离了单词的词形变化,因此“jumps”和“jumping”会匹配,但像“jmups”这样的拼写错误则不会匹配。

简而言之,SQLite FTS 扩展相当基础,并不意味着与 Google 等公司竞争。

至于 Django 集成,我不认为有。您可能需要使用 Django 的接口进行原始 SQL 查询,以创建和查询 FTS 表。

  • 所以简而言之,1)sqlite的FTS无法完成我所需要的。2)即使我为我的计算机[在sqlite3中启用FTS](http://stackoverflow.com/a/35011654/3375713),我也无法使用django的ORM(如`QScript.objects.filter(v__search ='egsample) ')`) 使用 FTS 功能。我得出这些结论对吗?如果是,你建议我做什么?谢谢。 (2认同)

Ale*_*zov 4

我认为虽然 sqlite 是一个令人惊叹的软件,但它的全文搜索功能非常有限。相反,您可以使用Haystack Django 应用程序和Elasticsearch等后端来索引数据库。在我看来,这样的设置(并且仍然能够访问您的 sqlite 数据库)是 FTS 方面最强大、最灵活的方式。

Elasticsearch 有一个基于 Levenshtein 距离的模糊搜索(简而言之,它将处理您的“egsample”查询)。因此,您所需要做的就是进行正确类型的查询:

from haystack.forms import SearchForm
from haystack.generic_views import SearchView
from haystack import indexes


class QScriptIndex(indexes.SearchIndex, indexes.Indexable):
    v = indexes.CharField(document=True)

    def get_model(self):
        return QScript


class QScriptSearchForm(SearchForm):
    text_fuzzy = forms.CharField(required=False)    

    def search(self):        
        sqs = super(QScriptSearchForm, self).search()

        if not self.is_valid():
            return self.no_query_found()

        text_fuzzy = self.cleaned_data.get('text_fuzzy')
        if text_fuzzy:
            sqs = sqs.filter(text__fuzzy=text_fuzzy)

        return sqs


class QScriptSearchView(SearchView):        
    form_class = QScriptSearchForm
Run Code Online (Sandbox Code Playgroud)

更新:只要PostgreSQL具有 Levenshtein 距离函数,您也可以将其用作 Haystack 后端以及独立的搜索引擎。如果您选择第二种方式,则必须实现自定义查询表达式,如果您使用的是最新版本的 Django,这相对容易。

  • 这并不能回答问题。这只是不同 FTS 解决方案的广告,没有任何理由说明它对于 OP 或其他任何人来说比 SQLite 更好。 (2认同)