代码之家  ›  专栏  ›  技术社区  ›  Sнаđошƒаӽ

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

  •  8
  • Sнаđошƒаӽ  · 技术社区  · 10 年前

    我正在使用sqlite3数据库开发一个django应用程序,它具有固定的数据库内容。固定的意思是数据库的内容不会随时间变化。模型如下:

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

    表中有大约6500条记录。给定一篇可能缺少一些单词或拼写错误的文本,我需要确定它的 ch_no 和 v_no 。例如,如果存在 v 带文本的数据库字段 “这是一首例句” ,给定的文本,如 “这是一首例句” 应该给我 频道(_N) 和 v_no(否) 来自数据库。我相信这可以使用全文搜索来完成。

    我的问题是:

    1. 全文搜索可以做到这一点吗?根据我所学的,我的猜测是可以的 sqlite3 page : 全文搜索是“谷歌、雅虎和必应对万维网上的文档所做的事情” 。引用于SO,我读到 this article 和其他许多人一样,但没有发现 紧密地 符合我的要求。

    2. 如何在django模型中使用FTS? 我读了 this 但这无济于事。它似乎太过时了。阅读 here 即: “…需要直接操作数据库才能添加全文索引” 。搜索主要提供与MySQL相关的信息,但我需要在sqlite3中进行搜索 直接操纵 在sqlite3中?


    编辑:

    我坚持使用sqlite3的选择正确吗?或者我应该使用不同的方法(如haystack+elasticsearch) Alex Morozov )? 我的数据库不会变大,我已经研究过小型数据库sqlite 几乎总是 更好(我的情况与第四 in sqlite's when to use checklist ).

    2 回复  |  直到 9 年前
        1
  •  5
  •   Colonel Thirty Two    10 年前

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

    有多种标记器可用,但它们相对简单。“简单”标记化器简单地将每个单词拆分并小写:例如,在字符串“The quick brown fox jumps over The lazy dog”中,单词“jumps”匹配,但不匹配“jump”。“搬运工”标记器更先进,去掉了单词的变位,这样“跳跃”和“跳跃”就匹配了,但像“jmups”这样的错别字就不匹配了。

    简而言之,SQLite FTS扩展是相当基本的,并不是要与谷歌竞争。

    至于Django集成,我认为没有。你可能需要 use Django's interface for raw SQL queries ,用于创建和查询FTS表。

        2
  •  3
  •   Alex Morozov    10 年前

    我认为,虽然sqlite是一款令人惊叹的软件,但它的全文搜索能力相当有限。相反,您可以使用 Haystack Django应用程序有一些后端 Elasticsearch 。在FTS方面,拥有这种设置(并且仍然能够访问您的sqlite数据库)对我来说似乎是最健壮和灵活的方式。

    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,这相对容易。