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

时间:2016-01-26 18:07:49

标签: python django sqlite full-text-search

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

class QScript(models.Model):
    ch_no = models.IntegerField()
    v_no = models.IntegerField()
    v = models.TextField()

表中有大约6500条记录。如果文字可能包含某些单词,或者某些单词拼写错误,我需要确定其ch_nov_no。例如,如果db中有一个v字段,其中包含文本"这是一个示例" ,一个给定的文本,如"这是一个egsample verse" 应该从db给我ch_nov_no。这可以使用我认为的全文搜索来完成。

我的疑问是:

  1. 可以全文搜索吗?根据我所研究的内容,我可以如sqlite3 page所说:全文搜索是"谷歌,雅虎和必应对万维网上的文件做了什么&#34 ; 。引用SO,我和其他许多人一起阅读this article,但没有发现密切符合我要求的任何内容。

  2. 如何在django模型中使用FTS?我看过this但它没有帮助。它似乎太过时了。阅读here" ...需要直接操纵数据库以添加全文索引" 。搜索主要提供MySQL相关信息,但我需要在sqlite3中完成。那么如何在sqlite3中做直接操作

  3. 编辑:

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

2 个答案:

答案 0 :(得分:2)

SQLite's FTS engine基于令牌 - 搜索引擎尝试匹配的关键字。

有各种各样的标记器,但它们相对简单。 "简单" tokenizer简单地将每个单词拆分并将其缩小:例如,在字符串中#34;快速的棕色狐狸跳过懒狗",单词"跳跃"会匹配,但不会#34;跳跃"。 "搬运工" tokenizer更先进一些,剥离了单词的结合,以便"跳跃"和"跳跃"会匹配,但是像#" jmups"不会。

简而言之,SQLite FTS扩展是相当基础的,并不意味着与谷歌竞争。

至于Django整合,我不相信有任何东西。您可能需要use Django's interface for raw SQL queries来创建和查询FTS表。

答案 1 :(得分:1)

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

Elasticsearch有一个fuzzy search基于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

更新:只要PostgreSQL具有Levenshtein距离功能,您也可以将其用作Haystack后端以及独立的搜索引擎。如果您选择第二种方式,则必须实施custom query expression,如果您使用的是最新版本的Django,则相对容易。