Django的__search与__contains的区别

laximzn5  于 2022-12-05  发布在  Go
关注(0)|答案(3)|浏览(180)

我最近才开始学习Django,所以如果这个问题对你来说太新手,请原谅我。
我在Django中实现了一个搜索功能。我在MySQL DB中创建了全文索引,然后在我的Book模型中有一个字段: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 + '*')

但是,如果我的搜索查询是“介绍”,而我知道有一个像“测试.介绍”这样的词/术语(如果术语只是“介绍”,那么它就工作得很好),上面的方法就不起作用了。
当我试着这样做的时候:

qs = qs.filter(keywords__icontains=search_keyword)

它找到“测试.介绍”等。
所以我开始想知道为什么会这样。“__search”只用于全词搜索吗?我知道“__contains”的情况是有道理的(不区分大小写并且包含单词的一部分),但是为什么要在DB中创建全文索引,这样我们就可以在Django中使用'__search'了呢?这是速度优势吗(例如,在大量文本需要搜索的情况下?还是我在这里完全遗漏了什么?

x6492ojm

x6492ojm1#

不同之处在于生成的SQL查询将在数据库上执行...我个人更喜欢“__contains”,因为它支持所有数据库,而“__search”只支持mysql(作为django docs)(* 在Django ≥ 1.10中也支持PostgreSQL * -参见documentation)。
查看每个方法的查询:

使用__搜索

>>> 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)'

使用__个容器

>>> 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% '
yrdbyhpb

yrdbyhpb2#

正如我所尝试的,__search只适用于多个单词中的整个单词(难以置信!),例如,当我的Book模型包含一个title='The little prance'对象时,而
国家.对象.filter(name__contais ='itt')
返回一个对象,
国家.对象.filter(name__search ='itt')
不返回任何内容!

5kgi1eie

5kgi1eie3#

搜索的优点是允许搜索多个字段:

>>> Entry.objects.annotate(
...     search=SearchVector('blog__tagline', 'body_text'),
... ).filter(search='cheese')
[
    <Entry: Cheese on Toast recipes>,
    <Entry: Pizza Recipes>,
    <Entry: Dairy farming in Argentina>,
]

相关问题