【问题标题】:Difference between Django's __search vs. __icontainsDjango 的 __search 与 __icontains 之间的区别
【发布时间】:2014-05-13 01:19:55
【问题描述】:

我最近才开始学习 Django,所以如果这个问题对你来说太新手,请原谅我。

我在 Django 中实现了一个搜索功能。我在 MySQL DB 全文索引中创建,然后在我的书籍模型中创建了一个字段:search_keywords,我基本上存储了所有单词,包括书籍的标题和内容。然后我的搜索功能会做类似的事情:

search_keyword = self.request.GET.get('keywords')
    if search_keyword:
        # '*' is added for cases where user enters only part of the keyword
        qs = qs.filter(keywords__search=search_keyword + '*')

但是,如果我的搜索查询是“intro”,而我知道有一个像“test.introduction”这样的词/术语(如果该术语只是“introduction”那么它可以正常工作),则上述方法不起作用。

然后当我尝试这个时:

        qs = qs.filter(keywords__icontains=search_keyword)

它会找到“test.introduction”等。

所以我开始想知道为什么会这样。 '__search' 是否仅用于全字搜索?我知道 '__icontains' 的大小写是有道理的(不区分大小写并包含单词的一部分),但是为什么要麻烦在数据库中创建全文索引,以便我们可以在 Django 中使用 '__search'?这是速度优势(例如,在要搜索大量文本的情况下?还是我在这里完全遗漏了什么?

【问题讨论】:

  • 不同的是,__search 不适用于 JSON_FIELD

标签: django full-text-search


【解决方案1】:

正如我所尝试的,__search 仅适用于多个单词中的整个单词(难以置信!),例如,当我的 Book 模型包含带有 title='The little prance' 的对象时,而

Country.objects.filter(name__contais='itt')

返回一个对象,

Country.objects.filter(name__search='itt')

什么都不返回!

【讨论】:

    【解决方案2】:

    不同之处在于要在数据库上执行的结果 SQL 查询...我个人更喜欢“__icontains”,因为所有数据库都支持,而“__search”仅适用于 mysql (as django docs) (也在 Django ≥ 1.10 中支持 PostgreSQL — 参见 documentation)。

    查看每个方法的查询:

    使用 __search

    >>> str(Contact.objects.filter(first_name__search='john').query)
    
    'SELECT `contact_contact`.`id`, `contact_contact`.`title`, `contact_contact`.`first_name`, `contact_contact`.`last_name`, `contact_contact`.`user_id`, `contact_contact`.`role_id`, `contact_contact`.`organization_id`, `contact_contact`.`dob`, `contact_contact`.`email`, `contact_contact`.`notes`, `contact_contact`.`create_date` FROM `contact_contact` WHERE MATCH (`contact_contact`.`first_name`) AGAINST (john IN BOOLEAN MODE)'
    

    使用 __icontains

    >>> str(Contact.objects.filter(first_name__icontains='john').query)
    
    'SELECT `contact_contact`.`id`, `contact_contact`.`title`, `contact_contact`.`first_name`, `contact_contact`.`last_name`, `contact_contact`.`user_id`, `contact_contact`.`role_id`, `contact_contact`.`organization_id`, `contact_contact`.`dob`, `contact_contact`.`email`, `contact_contact`.`notes`, `contact_contact`.`create_date` FROM `contact_contact` WHERE `contact_contact`.`first_name` LIKE %john% '
    

    【讨论】:

    • 谢谢@Darwin!这解释了很多。我还向您学习了如何检查 Django 的底层查询。 :)
    • 这可能有点错过领先...因为 __icontains 不被视为全文搜索。
    • 如果我尝试 __search 至少对于 PostgreSQL 有一个 NotImplementedError 并且完整的错误消息是“没有为此数据库后端实现全文搜索”。 Django 1.8 版
    • @akki,啊...我明白你的意思了!我对他说的是,我通过执行str(YourModelName.objects.filter(attributeName__search='something').query) 学会了查看 Django 在后台为我们创建的等效 SQL 语句。差不多就是这样。您也可以在上面的达尔文示例中看到它。希望有帮助??
    • 不知道我怎么错过了答案的那部分。谢谢:)
    猜你喜欢
    • 2019-08-24
    • 2020-10-30
    • 2019-04-09
    • 2014-10-30
    • 2021-12-07
    • 2016-02-09
    • 2016-05-14
    • 2016-10-11
    • 2015-06-02
    相关资源
    最近更新 更多