【问题标题】:How to use full-text search in sqlite3 database in django?如何在 django 的 sqlite3 数据库中使用全文搜索?
【发布时间】:2016-05-03 10:14:33
【问题描述】:

我正在开发一个带有 sqlite3 数据库的 django 应用程序,它具有固定的数据库内容。固定是指数据库的内容不会随着时间而改变。模型是这样的:

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

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

我的查询是:

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

  2. 如何在 django 模型中使用 FTS? 我阅读了 this,但没有帮助。似乎太陈旧了。阅读here“...需要直接操作数据库以添加全文索引”。搜索主要提供 MySQL 相关信息,但我需要在 sqlite3 中进行。那么如何在 sqlite3 中进行直接操作


编辑:

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

【问题讨论】:

    标签: python django sqlite full-text-search


    【解决方案1】:

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

    有多种标记器可用,但它们相对简单。 “simple”标记器只是将每个单词拆分并小写:例如,在字符串“The quick brown fox jumps over the lazy dog”中,单词“jumps”会匹配,但不会匹配“jump”。 “porter”分词器更高级一些,它去除了单词的共轭,因此“jumps”和“jumping”会匹配,但像“jmups”这样的拼写错误则不会。

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

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

    【讨论】:

    • 所以简而言之,1) sqlite 的 FTS 无法完成我所需要的。 2) 即使我enable FTS in sqlite3 用于我的电脑,我也不能使用django 的ORM(如QScript.objects.filter(v__search='egsample'))来使用FTS 功能。我对这些结论正确吗?如果是,你建议我做什么?谢谢。
    • 我写信是为了确认您可以在 Django 中使用 FTS。但是你需要use raw queries, or execute custom SQL directly。我个人倾向于后一种方法。有了它,您可以使用django.dbconnectionsrouters to 'switch' between different SQLite databases。这种方法允许我实现不同 SQLite 数据库之间接口的复杂查询,并且非常有用。
    【解决方案2】:

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

    Elasticsearch 有一个基于 Levenshtein 距离的fuzzy search(简而言之,它会处理您的“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,这相对容易。

    【讨论】:

    • 这不能回答问题。这只是一个不同 FTS 解决方案的广告,没有任何理由说明是什么使它比 SQLite 对 OP 或其他任何人更好。
    • 我快速浏览了一下 haystack。您知道 haystack 是否可以完成我在问题(搜索部分)中要求的内容吗?
    • 还有一件事。正如我在问题中所说,我的数据库永远不会增长,只会包含 1mb 的 unicode 文本。我应该去 haystack+elasticsearch 还是应该切换到 mysql 并使用它的 FTS,因为 sqlite3 的 FTS 没有模糊搜索?提前致谢!然后我最终会将您的标记为已接受;-)
    • 当然,你可以切换,但我推荐 PostgreSQL 而不是 Mysql,只要它有内置的 Levenshtein 函数,你只需要在它周围做一个薄包装。查看更新后的问题。
    • 其实我的意思是我是否应该使用任何提供模糊搜索的dbms(可能是mysql或postgresql,因为sqlite3没有),我应该使用OR hastack+elasticsearch,关于 我的数据库不会变得更大这一事实。关于我的情况,我期待您的建议,哪个是更好的选择。
    猜你喜欢
    • 2011-10-02
    • 2016-09-10
    • 2016-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    相关资源
    最近更新 更多